Zugang zu USB über Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Dienstag 11. April 2006, 17:43

Servus,

habe endlich die CD und die Steuerung gekriegt. Habe jetzt feststellen müssen, dass das Gerät einen anderen Treiber braucht. Es wurde nicht der NI-DAQ sondern der NI-DAQmx Treiber mitgeliefert. Ich habe jetzt auch noch von NI erfahren müssen, dass der mx Treiber eine andere dll enthält als der traditionelle (statt nidaq32.dll enthält es nicaiu.dll). Nicht nur das, auch die vom User lula in seinem Beitrag beschriebenen Funktionsaufrufe sind jetzt bei der anderen dll andere.
Ich habe mir mal erlaubt die Source von lula etwas zu modifizieren:

Code: Alles auswählen

from ctypes import *

pydll=windll.nicaiu                  # DLL geladen
AI_Read=pydll.DAQmxReadBinaryI16          # Funktion aus dll geladen
AO_Write=pydll.DAQmxWriteBinaryI16


# Analogwert einlesen
kanal=0
deviceNumber=c_int(1)             # i16 assigned by MAX
chan=c_int(kanal)
gain=c_int(-1)
h_ret=c_int(999)
status=AI_Read(deviceNumber,chan,gain,byref(h_ret))

# dig Input
deviceNumber=c_int(1)             # i16 assigned by MAX
port=c_int(0)
mode=c_int(0)
dir_=c_int(0)
line=c_int(1)
status=port_config(deviceNumber, port, line, dir_)
status =dig_input (deviceNumber, port, line,byref(h_ret))


Ich weiss aber nicht ob dies stimmt. Falls sich hier einer mit der nicaiu.dll auskennt, wäre ich außerordentlich dankbar, wenn er sich hier dazu äußern könnte.

Gruss,
Toni

Edit (Leonidas): Code in Python-Tags gesetzt.
lula
User
Beiträge: 3
Registriert: Samstag 8. April 2006, 13:15
Wohnort: Leipzig

Beitragvon lula » Dienstag 11. April 2006, 18:06

Hallo Toni83,

Ich habe bisher nur mit dem traditionellen NI-DAC gearbeitet, kenne mich also in der nicaiu.dll nicht aus.
NI liefert meist Beispiele in VB oder C/C++ mit. Vielleicht kannst Du dort die Aufrufkonventionen ableiten.

Tschüß Lutz
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Dienstag 11. April 2006, 20:22

Ich glaube ich muss da selber durch...
Danke für die Antwort lula!
Werde mal schauen ob ich etwas in Erfahrung bringe. Werde dann auf jeden Fall wenn ich Erfolg habe, den Source hier für die Nachwelt ins Forum stellen.
Danke erstmal allen für die Hilfe.

Gruss,
Toni
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Mittwoch 12. April 2006, 22:36

Habe da nocmal ein Problem. Habe jetzt möglichen Source gefunden:

static TaskHandle ghProcessTask=0;

// Analog Out (static) ------------------------------------------------------
DAQmxCreateTask("", &ghProcessTask);
DAQmxCreateAOVoltageChan(ghProcessTask, ProcessChannel, "", -amplitude, amplitude, DAQmx_Val_Volts, NULL);
DAQmxCfgOutputBuffer (ghProcessTask, 0);

DAQmxStartTask(ghProcessTask);
while(gRunning){
DAQmxWriteAnalogScalarF64 (ghProcessTask, 0, 10.0, data[++i%bufferSize], 0);
Delay(0.05);
}
DAQmxCleanTask(ghProcessTask);

Problem: &ghProcessTask und static TaskHandle ghProcessTask=0;
Wie löse ich das in Python? Gibt es da eine Möglichkeit mit ctypes?

Gruss,
Toni
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Mittwoch 19. April 2006, 20:00

Habe inzwischen eine Lösung gefunden. Problem dabei:
Der Code ist in C geschrieben, da ich für den neuen Treiber NIDAQmx keine Möglichkeit sehe diesen in Python zu schreiben.
Nun weiss ich leider nicht wie ich meinen C-Code bzw. mein angelegtes Projekt (enthält 2 Programme) in Python einbinde. Im Prinzip will ich nur einen Wert aus dem C-Code in Python zurückgeben. Wie ich allerdings den Code von Python aufrufe weiss ich leider nicht und benötige da eure Hilfe...

Gruss,
Toni

P.S.: Wer gleiche oder ähnliche Probleme hat, hier der Code: (Ich hoffe es bringt euch weiter :D)

USB 6009 (Auslesen eines Spannungswerts):

Code: Alles auswählen

#include <stdio.h>
#include <NIDAQmx.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void)
{
   int32       error=0;
   TaskHandle  taskHandle=0;
   int32       read;
   float64     data[1000];
   char        errBuff[2048]={'\0'};

   /*********************************************/
   // DAQmx Configure Code
   /*********************************************/

   DAQmxErrChk (DAQmxCreateTask("",&taskHandle));

   DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));
   DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000));

   /*********************************************/
   // DAQmx Start Code
   /*********************************************/
   DAQmxErrChk (DAQmxStartTask(taskHandle));

   /*********************************************/
   // DAQmx Read Code
   /*********************************************/

   DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,&read,NULL));

   /*********************************************/
   // Read Voltage Input
   /*********************************************/

   printf("Acquired %f points\n",data[0]);
   
      

Error:
   if( DAQmxFailed(error) )
      DAQmxGetExtendedErrorInfo(errBuff,2048);
   if( taskHandle!=0 )  {
      /*********************************************/
      // DAQmx Stop Code
      /*********************************************/
      DAQmxStopTask(taskHandle);
      DAQmxClearTask(taskHandle);
   }
   if( DAQmxFailed(error) )
      printf("DAQmx Error: %s\n",errBuff);
   printf("End of program, press Enter key to quit\n");
   getchar();
   return 0;
}


Und NIDAQmx.c für das dll Handling. (Falls jemand dies benötigt dem kann ich das schicken, da der Code dazu zu lang wäre um in an dieser Stelle zu senden.)
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Mittwoch 19. April 2006, 21:21

Toni83 hat geschrieben:Wie ich allerdings den Code von Python aufrufe weiss ich leider nicht und benötige da eure Hilfe...

Dazu gibt es mehrere möglichkeiten. Du kannst versuchen, den C-Code als DLL zu kompilieren und mit ctypes zugreifen, oder du kannst es mit vergleichsweise einfach SWIG oder Pyrex wrappen. Für nährere Details wartest du auf modelnine ;)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Mittwoch 19. April 2006, 22:46

Danke für die Anwort!
Aus dem Code eine dll zu erstellen habe ich noch nie gemacht. Wird also für mich sehr schwierig werden.
Da schaue ich mir doch lieber die Wrapper an. Werde mich noch selber darüber informieren, allerdings wäre ich modelnine sehr dankbar wenn er Zeit finden würde mir ein paar "Details" über die Wrapper mitzuteilen.
Danke!

Gruss,
Toni
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Beitragvon modelnine » Donnerstag 20. April 2006, 07:22

Humm... Am besten schickst Du einfach mal ein bisschen Code, oder stellst den "Wrapper" der über dem liegt den Du jetzt geschrieben hast irgendwo im Netz zum Download zur Verfügung, dann kann ich gerne mal gucken inwiefern ich dazu einen Python-Wrapper schreiben kann. Das ist im Normalfall nicht schwer. Sonst, wenn Du allgemeine Fragen zum Wrappen hast, stell sie einfach!

Auf jeden Fall sehenswert ist:

http://docs.python.org/ext/ext.html

Kapitel 1 und 2, um die Grundzüge zu verstehen wie man ein Python-Erweiterung in C schreibt, und sonst natürlich auch noch:

http://docs.python.org/api/api.html

die API-Dokumentation zu Python, die sehr hilfreich ist um eine Übersicht über die Konversionsfunktionen von C-Typen zu Python-Typen und umgekehrt zu bekommen.

Wie gesagt, poste einfach Code der gewrappt werden muß, und ich kann Dir gerne einen Beispielwrapper schreiben zum angucken.
--- Heiko.
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Donnerstag 20. April 2006, 16:15

Danke für das Angebot! Wenn Du ein wenig Zeit für diese Sache entbehren könntest und es nicht großen Aufwand macht kannst Du sehr gerne einen Beispielwrapper schreiben. Wäre Dir außerordentlich dankbar dafür, da ich aus meiner Sicht denke, dass dies nicht so einfach sein wird.
Warum? Weil es zwei C-Dateien sind. Diese müssen unbedingt in einem Projekt eingebunden sein, da der Code sonst nicht funktionieren würde. In der einen Datei (NIDAQmx.c) sind Definitionen für die Ansteuerungen meines USB-Gerätes vorhanden, die die zweite Datei (USB6009.c) benötigt.

Hier der Code:

NIDAQmx.c:

Findet man unter:
http://forums.ni.com/attachments/ni/250 ... /NIDAQmx.c

und USB6009:

Code: Alles auswählen

#include <stdio.h>
#include <NIDAQmx.h>

#define DAQmxErrChk(functionCall) if( DAQmxFailed(error=(functionCall)) ) goto Error; else

int main(void)
{
   int32       error=0;
   TaskHandle  taskHandle=0;
   int32       read;
   float64     data[1000];
   char        errBuff[2048]={'\0'};

   /*********************************************/
   // DAQmx Configure Code
   /*********************************************/

   DAQmxErrChk (DAQmxCreateTask("",&taskHandle));

   DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));
   DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,1000));

   /*********************************************/
   // DAQmx Start Code
   /*********************************************/
   DAQmxErrChk (DAQmxStartTask(taskHandle));

   /*********************************************/
   // DAQmx Read Code
   /*********************************************/


   DAQmxErrChk (DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByChannel,data,1000,&read,NULL));

   printf("Acquired %f points\n",data[0]);
   
      

Error:
   if( DAQmxFailed(error) )
      DAQmxGetExtendedErrorInfo(errBuff,2048);
   if( taskHandle!=0 )  {
      /*********************************************/
      // DAQmx Stop Code
      /*********************************************/
      DAQmxStopTask(taskHandle);
      DAQmxClearTask(taskHandle);
   }
   if( DAQmxFailed(error) )
      printf("DAQmx Error: %s\n",errBuff);
   printf("End of program, press Enter key to quit\n");
   getchar();
   return 0;
}



Nochmals Danke im Voraus!!!

Gruss,
Toni

P.S.: Nur mal so am Rande: Gibt es irgendeine Möglichkeit den Code auch als z.B. zip Datei hochzuladen und einzubinden?
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Donnerstag 20. April 2006, 16:34

Toni83 hat geschrieben:P.S.: Nur mal so am Rande: Gibt es irgendeine Möglichkeit den Code auch als z.B. zip Datei hochzuladen und einzubinden?

Im Forum? Nein. Das phpBB (die Forensoftware) zu modifizieren wäre möglich aber der aufwand wäre zu groß, da dieses Feature eigentlich kaum jemand braucht.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Beitragvon modelnine » Samstag 22. April 2006, 16:09

Toni83, bevor Du Dich fragst, wo der Code bleibt: ich hab erst jetzt am Wochenende wirklich Zeit gefunden mich dranzusetzen; ich werd schauen, dass ich morgen mittag mal ein kleines Beispielscript poste, was die Funktionalität deines Benutzungsskriptes dupliziert. Solange bitte noch gedulden, ich habs nicht vergessen. ;-)
--- Heiko.
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Mittwoch 26. April 2006, 16:14

Ich schätze mal, dass modelnine leider keine Zeit findet um eine Beispielsource zu senden. Habe jetzt SWIG installiert. Habe ein einfacheres Programm geschrieben, es funktioniert aber leider nicht...
Warum? weiss ich auch nicht!

Code:

example.c:

Code: Alles auswählen

/* File : example.c */

#include <time.h>
double My_variable = 3.0;

int fact (int n) {
   if (n <= 1) return 1;
   else return n*fact(n-1);
}

int my_mod(int x, int y) {
   return (x%y);
}

char *get_time()
{
   time_t ltime;
   time(<ime);
   return ctime(<ime);
}


example.i:

Code: Alles auswählen

/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}

extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();


Bin dann auf der Eingabeaufforderung fortgefahren:

swig -python -c++ example.i
c++ -c example.c -I/usr/local/include/python2.3
c++ -shared example.o -o _example.so

Nachdem sollte mit import example die ursprüngliche C-Source in Python vorhanden sein. Stattdessen kommt die Fehlermeldung:

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "example.py", line 5, in ?
import _example
ImportError: No module named _example

Kann mir jemand das bitte erklären?

Gruss,
Toni
Benutzeravatar
Toni83
User
Beiträge: 125
Registriert: Donnerstag 28. Juli 2005, 10:53

Beitragvon Toni83 » Donnerstag 4. Mai 2006, 15:41

Habe jetzt die ganze letzte Zeit mit dem wrappen zugebracht. Leider ohne Erfolg. Scheint aus meiner Sicht irgendwie nicht möglich meinen Code zu wrappen.
Habe dann daraufhin eine .dll aus meiner C-Datei mit VC++ 6.0 erstellt und diese dann mit ctypes aus Python heraus aufgerufen. Geht ganz schnell und unkompliziert im Gegensatz zum wrappen.
Falls es jemanden interessiert wie dies geht, dem kann ich das vorgehen dann an dieser Stelle posten.

Gruss,
Toni

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder