Al een poosje ben ik aan het stoeien met Python, en dit gaat mij redelijk af.
Nu ben ik bezig met een groot script waarbij ik de paralelle poort wil aansturen. Dit is me gelukt met de module ctypes, maar wat blijkt, het is niet mogelijk om de paralelle poort meer dan ongeveer 100 maal per seconde te verversen terwijl ik rond te 900 kHz / 1 MHz wil zitten. Ik ben erachter gekomen dat dit ergens in Python zit ingebakken. Ook wanneer ik het DLL-bestand simpleio van de module pyparallel gebruikt heb ik dit probleem.
Uit frustratie ben ik met mijn gebrekkige C een extention gaan schrijven.
Mijn kennis in C heb ik opgedaan met het schrijven van kleine programmatjes voor microcontrollers.
Het komt erop neer dat ik de extention wel kan importeren in Python, maar de functies het goed werken -> ze doen niks tot weinig.
Ik denk dat dat de structuur van deze extention wel klopt, maar waar zijn de fouten, dingen zoals refrence count, verkeert gebruik van functies enz.
Misschien is het gewoon een kwestie van de klok en de klepel.
Hieronder is de code te lezen die ik tot nu toe geklopt heb. Het is nog niet helemaal af, maar het zou moeten kunnen werken.
edit
Zal je net zien dat je er een fout uit haalt. En nu geeft het een "Toepassingsfout", namelijk "een lees- of schrijfbewerking ("written") op het geheugen is mislukt."
Nu ben ik bezig met een groot script waarbij ik de paralelle poort wil aansturen. Dit is me gelukt met de module ctypes, maar wat blijkt, het is niet mogelijk om de paralelle poort meer dan ongeveer 100 maal per seconde te verversen terwijl ik rond te 900 kHz / 1 MHz wil zitten. Ik ben erachter gekomen dat dit ergens in Python zit ingebakken. Ook wanneer ik het DLL-bestand simpleio van de module pyparallel gebruikt heb ik dit probleem.
Uit frustratie ben ik met mijn gebrekkige C een extention gaan schrijven.
Mijn kennis in C heb ik opgedaan met het schrijven van kleine programmatjes voor microcontrollers.
Het komt erop neer dat ik de extention wel kan importeren in Python, maar de functies het goed werken -> ze doen niks tot weinig.
Ik denk dat dat de structuur van deze extention wel klopt, maar waar zijn de fouten, dingen zoals refrence count, verkeert gebruik van functies enz.
Misschien is het gewoon een kwestie van de klok en de klepel.
Hieronder is de code te lezen die ik tot nu toe geklopt heb. Het is nog niet helemaal af, maar het zou moeten kunnen werken.
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
| /*********************** Functieomschrijving ************************************** ** Deze dll/pyd heeft als doel bij een vooraf bepaalde tijd de registers van ** de paralelle poort te vernieuwen en uit te lezen. ** De waardes die in de registers gestopt worden, worden opgeslagen in ** een buffer die bij het starten van de connectie bepaald wordt. ** De data die deze functies verwerken zijn Python-objecten (Lists). ** Hierdoor hoeft er in Python niet gerotzooid worden met de module ctypes. **********************************************************************************/ #include <Python.h> #include <Windows.h> #include <conio.h> /* Een sturct om de argumenten aan de thread door te geven */ struct threadArg{ int poort; int verversTijd; }; /* Declareren van functies */ __declspec(dllexport) PyObject* start(PyObject*, PyObject*); __declspec(dllexport) PyObject* stop(PyObject*, PyObject*); __declspec(dllexport) PyObject* pauze(PyObject*, PyObject*); __declspec(dllexport) PyObject* setData(PyObject*, PyObject*); __declspec(dllexport) PyObject* dataBuffer(PyObject*, PyObject*); __declspec(dllexport) PyObject* setControl(PyObject*, PyObject*); __declspec(dllexport) PyObject* controlBuffer(PyObject*, PyObject*); __declspec(dllexport) PyObject* getStatus(PyObject*, PyObject*); __declspec(dllexport) PyObject* statusBuffer(PyObject*, PyObject*); DWORD WINAPI threadFunc(struct threadArg *); /* Pointers die wijzen naar het begin van de buffer */ long long *ptrDataBuf, *ptrControlBuf, *ptrStatusBuf; /* Variabelen die aangeven hoeveel elementen er in de buffer staan */ unsigned int lenDataBuf=0, lenControlBuf=0, lenStatusBuf=0, lenBuffer=0; /* Een handle voor de thread */ HANDLE hThread; /* Geeft aan of de thread actief, gepauseerd of gestopt is. 0 = thread NIET actief, 1 = thread actief, 2 = thread gepauseerd */ int thread_actief=0; /* Start de connectie met de paralelle poort */ __declspec(dllexport) PyObject *start(PyObject *self , PyObject *args) { struct threadArg arg; int buffer; /* Argumenten in de struct stoppen */ if( !PyArg_ParseTuple(args, "iii", &arg.verversTijd, &arg.poort, &lenBuffer) ){ /* Later nog een fout eruit gooien? */ return Py_None; } if( !thread_actief ){ /* De buffers bij het Windows(R) reserveren */ ptrDataBuf = calloc( lenBuffer, sizeof(int) ); ptrControlBuf = calloc( lenBuffer, sizeof(int) ); ptrStatusBuf = calloc( lenBuffer, sizeof(int) ); /* De thread starten wanneer alle argumenten gegeven zijn */ if( arg.verversTijd && arg.poort && lenBuffer ){ thread_actief = 1; hThread = CreateThread( 0, 0, threadFunc, &arg, 0, 0 ); } } return Py_None; } /* Stopt de connectie met de paralelle poort */ __declspec(dllexport) PyObject *stop(PyObject *self , PyObject *args) { if( thread_actief ){ thread_actief = 0; /* Wachten tot de thread gestopt is */ WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); /* De buffers terug geven aan Windows(R) */ free(ptrDataBuf); free(ptrControlBuf); free(ptrStatusBuf); /* De bufferlengte zetten */ lenBuffer = 0; } return Py_None; } /* Pauseer de connectie met de paralelle poort */ __declspec(dllexport) PyObject *pauze(PyObject *self , PyObject *args) { /* Spreekt voor zich */ if(thread_actief == 2){ thread_actief = 0; } else{ thread_actief = 2; } return Py_None; } /* Zet de data in de 'dataBuffer' */ __declspec(dllexport) PyObject *setData(PyObject *self, PyObject *args) { PyObject *lijst, *PyItem; int i, n, temp; static int index=0; /* Argument ontleden */ if( !PyArg_ParseTuple(args, "O", &lijst) ){ /* Later nog een fout eruit gooien? */ return Py_None; } /* Alle waardes uit de integer halen en in de buffer zetten */ n = PyList_Size(lijst); /* Als de lijst 'leeg' is, return */ if( n==0 ){ return Py_None; } for( i=0 ; i<n ; i++ ){ PyItem = PyList_GetItem(lijst, i); if( PyInt_Check(PyItem) ){ /* Wanneer het getal meer is dan in de register past, overslaan */ if( -1 < PyInt_AsLong(PyItem) < 256 ){ *(ptrDataBuf + index) = PyInt_AsLong(PyItem); /* Wanneer de buffer vol zit, niet meer de teller verhogen */ if(lenDataBuf < lenBuffer){ lenDataBuf++; } } /* Wanneer aan de eind van de array, weer terug naar het begin */ (index < lenBuffer) ? index++ : (index=0); } } return Py_None; } /* Geeft aan hoeveel waardens in de 'dataBuffer' aanwezig zijn */ __declspec(dllexport) PyObject *dataBuffer(PyObject *self , PyObject *args) { PyObject *terug; terug = PyInt_FromLong(lenDataBuf); Py_INCREF(terug); return terug; } /* Zet de data in de 'controlBuffer' */ __declspec(dllexport) PyObject *setControl(PyObject *self, PyObject *args) { PyObject *lijst, *PyItem; int i, n, temp; static int index=0; /* Argument ontleden */ if( !PyArg_ParseTuple(args, "O", &lijst) ){ /* Later nog een fout eruit gooien? */ return Py_None; } /* Alle waardes uit de integer halen en in de buffer zetten */ n = PyList_Size(lijst); /* Als de lijst 'leeg' is, return */ if( n==0 ){ return Py_None; } for( i=0 ; i<n ; i++ ){ PyItem = PyList_GetItem(lijst, i); if( PyInt_Check(PyItem) ){ /* Wanneer het getal meer is dan in de register past, overslaan */ if( -1 < PyInt_AsLong(PyItem) < 256 ){ *(ptrControlBuf + index) = PyInt_AsLong(PyItem); /* Wanneer de buffer vol zit, niet meer de teller verhogen */ if(lenControlBuf < lenBuffer){ lenControlBuf++; } } /* Wanneer aan de eind van de array, weer terug naar het begin */ (index < lenBuffer) ? index++ : (index=0); } } return Py_None; } /* Geeft aan hoeveel waardens in de 'controlBuffer' aanwezig zijn */ __declspec(dllexport) PyObject *controlBuffer(PyObject *self , PyObject *args) { PyObject *terug; terug = PyInt_FromLong(lenControlBuf); Py_INCREF(terug); return terug; } /* Geeft de inhoud van de 'statusBuffer' terug als een lijst */ __declspec(dllexport) PyObject *getStatus(PyObject *self , PyObject *args) { PyObject *PyLijst; PyObject *PyInt; static int index=0; PyLijst = PyList_New(0); Py_INCREF(PyLijst); while( lenStatusBuf ){ /* De inhoud van de statusbuffer in een lijst omzetten */ PyInt = PyInt_FromLong( *(ptrStatusBuf + index) ); PyList_Append(PyLijst, PyInt); lenStatusBuf--; /* Wanneer aan de eind van de array, weer terug naar het begin */ (index < lenBuffer) ? index++ : (index=0); } return PyLijst; } /* Geeft aan hoeveel waardens in de 'statusBuffer' aanwezig zijn */ __declspec(dllexport) PyObject *statusBuffer(PyObject *self , PyObject *args) { PyObject *terug; terug = PyInt_FromLong(lenStatusBuf); Py_INCREF(terug); return terug; } /* De thread zorgt voor een real-time uitlezing/afhandeling van de data */ DWORD WINAPI threadFunc(struct threadArg *ptrArg) { int dataReg, controlReg, statusReg; int indexData=0, indexControl=0, indexStatus=0; HANDLE hTimer; HANDLE hPoort; /* De waarde voor de timer berekenen */ long long tijd = ptrArg -> verversTijd * -10000000; /* De tijd in 100 ns */ /* Adressen van de registers berekenen */ dataReg = ptrArg -> poort; controlReg = dataReg + 1; statusReg = dataReg + 2; /* Handlers maken */ hTimer = CreateWaitableTimer(NULL, 0, NULL); hPoort = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); while( thread_actief ){ /* Pauze, wachten */ while( thread_actief == 2 ){ SetWaitableTimer(hTimer, &tijd, 0, 0, 0, 0); WaitForSingleObject(hTimer, INFINITE); } SetWaitableTimer(hTimer, &tijd, 0, 0, 0, 0); /* Hier is een mooi stukje programma dat je kan doen terwijl je toch aan het wachten bent. */ if( lenDataBuf > 0 ){ /* Het aantal elementen in de buffer met 1 verminderen */ lenDataBuf--; /* Wanneer het eind van de buffer nog NIET berijkt is, naar de volgende element wijzen. Anders naar het begin */ (indexData < lenBuffer) ? indexData++ : (indexData=0); } if( lenControlBuf > 0 ){ /* Het aantal elementen in de buffer met 1 verminderen */ lenControlBuf--; /* Wanneer het eind van de buffer nog NIET berijkt is, naar de volgende element wijzen. Anders naar het begin */ (indexControl < lenBuffer) ? indexControl++ : (indexControl=0); } /* Trigger als de tijd om is */ WaitForSingleObject(hTimer, INFINITE); /* Data in de registers zetten / uitlezen */ _outp( dataReg, *(ptrDataBuf + indexData) ); _outp( controlReg, *(ptrControlBuf + indexControl) ); *(ptrStatusBuf + indexStatus) = _inp(statusReg); /* Wanneer het eind van de buffer nog NIET berijkt is, naar de volgende element wijzen. Anders naar het begin */ (indexStatus < lenBuffer) ? indexStatus++ : (indexStatus=0); /* Wanneer de buffer vol zit, niet meer de teller verhogen */ if(lenStatusBuf < lenBuffer){ lenStatusBuf++; } } CloseHandle(hTimer); CloseHandle(hPoort); return 0; } char pypar_doc[] = "Deze module is te gebruiken voor communicatie met de paralelle poort.\nHierbij wordt door een vooraf vastgestelde tijd de data aan de poort ververst en uitgelezen."; static char start_func_doc[] = "Met deze functie wordt de connectie met de paralelle poort gestart"; static char stop_func_doc[] = "Stopt de connectie met de paralelle poort."; static char setData_func_doc[] = "Zet de items van de list in de buffer van de dataregister"; static char pauze_func_doc[] = "Pauzeer de connectie met de paralelle poort."; static char dataBuffer_func_doc[] = "Dit is een string."; static char setControl_func_doc[] = "En dit is er ook een."; static char controlBuffer_func_doc[] = "En deze."; static char getStatus_func_doc[] = "Deze ook"; static char statusBuffer_func_doc[] = "Vooruit dan maar, deze ook."; static PyMethodDef pyparMethods[] = { /* Naam van de functie in Python, pointer naar de functie in C, type argument, doc string */ {"start", start, METH_VARARGS, start_func_doc}, {"stop", stop, METH_NOARGS, stop_func_doc}, {"pauze", pauze, METH_NOARGS, pauze_func_doc}, {"setData", setData, METH_VARARGS, setData_func_doc}, {"dataBuffer", dataBuffer, METH_NOARGS, dataBuffer_func_doc}, {"setControl", setControl, METH_VARARGS, setControl_func_doc}, {"controlBuffer", controlBuffer, METH_NOARGS, controlBuffer_func_doc}, {"getStatus", getStatus, METH_NOARGS, getStatus_func_doc}, {"statusBuffer", statusBuffer, METH_NOARGS, statusBuffer_func_doc}, {NULL, NULL, 0, NULL} }; /* Initialisatie van de Python module */ __declspec(dllexport) void initpypar(void){ Py_InitModule3("pypar", /* naam van de module */ pyparMethods, /* naam van de methode tabel */ pypar_doc); /* doc string voor de module */ } |
edit
Zal je net zien dat je er een fout uit haalt. En nu geeft het een "Toepassingsfout", namelijk "een lees- of schrijfbewerking ("written") op het geheugen is mislukt."
[ Voor 3% gewijzigd door Verwijderd op 17-06-2006 23:12 ]