2016-06-17 18 views
1

Ich schreibe einen Code, um die Spannungsmessungen von mehreren Sensoren über SPI zu protokollieren. Ich speichere alle Daten in einer benutzerdefinierten Datenstruktur und drucke dann die Datenstruktur auf das Terminal, wenn entweder zu viele Ereignisse aufgetreten sind oder ein Benutzer die Daten anfordert. Das Problem, das ich finde, ist, dass der letzte Datenwert in jedem Ereignis vollständig falsch ist, wenn ich die DataDump-Funktion aufruft. Wenn ich versuche, die Daten sofort nach der Aufzeichnung zu drucken, ist es korrekt. Ich habe, was ich denke, sind die wichtigen Code-Spinets unten, aber hier ist ein Link zum gesamten Programm http://pastebin.com/Y7kcntu3.Drucken von Müll

Mein einziger Gedanke, was das sein könnte, ist, wenn ich den Speicher für die 200 Ereignisse zugeordnet, der Umfang der Struktur erstreckt sich nicht auf die Funktion DumpData. Aber das macht keinen Sinn, da alle anderen Daten vorhanden und korrekt sind. Mein anderer Gedanke ist, dass es bei der Konvertierung von char-> Binary-> decimal einen anderen Fehler gibt, aber auch hier ist nur der einzelne Wert falsch.

Dieser erste Codeabschnitt ist eine Datenstruktur, die ich erstellt habe, um die Daten von mehreren Sensoren zu verarbeiten. Die Daten sind nur 8-Bit-SPI-Daten von einem ADC, so dass ich nicht signierte Zeichen verwendete, um den verwendeten Speicher zu minimieren. Ich habe auch genug Speicher für 200 Ereignisse reserviert.

typedef struct    //event structure, containts a timestamp element and an array of 18 data points 
{ 
    unsigned long int timeStamp; 
    unsigned char data[SENSORS]; 
} Event; 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

Event eventLog[MAX_DATA];  //an array of structures representing 200 events, once the 200 events have been filled the data will be printed 

In Main "loop()", wenn ein Stift dort hoch ist, ist ein Datensammelprozess. Wenn eine gerade auftritt, wird die erste Ereignisdatenstruktur einen Zeitstempel aufzeichnen, der dann der Prozess ist, Analog-Digital-Umwandlungen zu starten und die Daten in dem Datenfeld für das aktuelle Ereignis zu speichern.

eventLog[i].timeStamp = micros(); 

    for (j=0; j<=SENSORS; ++j) { 
     lockAndPop();       //lock digital value and reset conversion 
     selector = inputSelector(selector);  //increment the selector pin 
     PORTA = selector; 
     digitalWrite(RD, LOW);    //Start new conversion 

     digitalWrite(CLK_INH, LOW);    //Start the data transfer 
     eventLog[i].data[j] = SPI.transfer(0);  //read a single byte from the SPI line 
     digitalWrite(CLK_INH, HIGH);    //Inhibit clock 
     digitalWrite(LD, LOW); 
     while(digitalRead(INT1)){}    //wait for previous conversion to end    
     } 
    i++; 

Die Daten-Dump-Funktion in zwei Situationen genannt wird, die erste, wenn 200 Ereignisse eingetreten sind, sind die Sekunden, wenn eine externe Taste ausgeschaltet ist gepresst. Diese Funktion erstellt einen Druckpuffer, mit dem die Ereignisdaten formatiert und als Dezimalwert angezeigt werden können. Die Datenwerte werden von Binär in Dezimal, nicht ASCII konvertiert.

void dataDump(){ 
    char buf[100], *pos = buf; //create a buffer of 100 charaters, anda pointer to the begining of that buffer 
    char *base = buf;    //create a base address to reset the buffer 
    unsigned char eventCount = i;    //how many events occured before dump command was called 
    unsigned char localCount;  
    unsigned char localData; 
    Serial.begin(115200); 
    for (localCount = 0; localCount<=eventCount; ++localCount){ 
    pos += sprintf(pos, "%lu", eventLog[localCount].timeStamp);   //sprintf will append the data to the pointer "pos", and return the number of byte append. 
    for (localData = 0; localData<=SENSORS; ++localData){ 
     pos += sprintf(pos, " %d", (unsigned int)(eventLog[localCount].data[localData])); 
    } 
    Serial.println(buf); 
    pos = base; 
    } 
    i=0; 
    j=0; 
    Serial.end(); 
    return; 

Das Problem, das ich mit Blick auf bin, ist, dass, wenn die Daten-Dump-Funktion aufgerufen wird, alles mit Ausnahme des letzten Datenwertes in der Matrix fein gedruckt wird. Hier ist ein Beispiel dafür, was

gedruckt wird
539580840 171 149 120 152 
539581080 170 149 119 216 
539581912 170 149 120 196 
539582148 170 149 120 180 
539582388 170 149 120 168 
539582632 170 149 119 148 
539582868 170 148 119 128 
539583104 170 149 119 216 
539583704 170 149 120 196 
539583940 170 149 120 176 
539584176 170 149 120 160 
539584416 170 149 120 148 
539584660 170 149 120 128 
539584896 170 149 120 112 
539585136 170 149 120 92 
539585372 170 149 119 80 
539585616 170 149 120 60 
539585852 170 149 119 59 

Der letzte Wert sollte wie die drei, bevor sie konstant sein, wie der ADC eine Referenzspannung liest. Die Daten sind beim Drucken einwandfrei

Serial.println(eventLog[i].data[3]) 

aus dem Hauptcode "loop()". Ich habe versucht, den gleichen Code aus den Daten-Dump-Funktionen auszuführen, aber ich bekomme immer noch Müll. Außerdem habe ich die SPI-Leitung mit einem Logikanalysator überwacht, und ich sehe die Daten, die ich auf der Datenleitung sehen sollte.

** Mein einziger Gedanke, was dies sein könnte, ist, wenn ich den Speicher für die 200 Ereignisse zugewiesen, der Umfang der Struktur erstreckt sich nicht auf die Funktion DumpData. Aber das macht keinen Sinn, da alle anderen Daten vorhanden sind. **

+0

Welches Board verwenden Sie? Und was ist der Wert von 'SENSORS'? –

+0

SENSOREN = 3, also erwarte ich 4 Messungen. Ich benutze ein Mega 2560 – Lpaulson

Antwort

1

Ich habe es zuerst nicht bemerkt, aber sobald Sie meine Fragen beantwortet haben, steckte es wie ein wunde Daumen. Wenn SENSORS gleich drei ist, dann ist ein Array von drei Elementen. Nicht vier, wie du es erwartest.

Arrays werden mit einem nullbasierten Index (0,1,2,3, ...) verwendet. Wenn Sie sie jedoch deklarieren, müssen Sie die tatsächliche Anzahl der benötigten Elemente angeben.

Um zu beheben, würde ich SENSORS gleich vier machen, dann passen Sie Ihre Schleifen von Null auf weniger als SENSORS (nicht kleiner oder gleich). Das gleiche gilt für MAX_DATA. Ihre Schleifen verwenden ein weiteres Element, als Sie tatsächlich besitzen.

Sofern Sie keinen Index benötigen, verfügt C++ 11 über eine Funktion, die das Überlaufen Ihrer Arrays verhindert. Es ist die Entfernungsschleife.

Die Schleife Sie jetzt verwenden:

for (localCount = 0; localCount<=eventCount; ++localCount){ 
    pos += sprintf(pos, "%lu", eventLog[localCount].timeStamp);   //sprintf will append the data to the pointer "pos", and return the number of byte append. 
    for (localData = 0; localData<=SENSORS; ++localData){ 
    pos += sprintf(pos, " %d", (unsigned int)(eventLog[localCount].data[localData])); 
    } 
    Serial.println(buf); 
    pos = base; 
} 

dies werden kann:

for(auto &entry : eventLog){ 
    pos += sprintf(pos, "%lu", entry.timeStamp); 
    for(char reading : entry.data){ 
    pos += sprintf(pos, " %d", (unsigned int)reading); 
    } 
    Serial.println(buf); 
    pos = base; 
} 

Da es keine Indizes beteiligt sind, werden Sie immer die aktuelle Anzahl von Elementen verwenden. Entfernte Schleifen können anfangs ziemlich verwirrend sein, sind aber sehr nützlich.

Und Befestigung der Verwendung von SENSORS und MAX_DATA möglicherweise nicht alle Probleme lösen, aber beheben Sie das, dann können wir den Rest betrachten, wenn Ihr Problem weiterhin besteht. Wenn es mehr Probleme gibt, lassen Sie einige Informationen in den Kommentaren unten und ich werde meine Antwort aktualisieren.

+0

Also wenn ich das richtig verstehe, wenn ich zu EventLog [i] .data [3] schrieb, schrieb ich höchstwahrscheinlich an die Adresse von EventLog [i + 1] .timeStamp. Dies ist der Grund, warum ich beim Drucken von eventLog [i] .data [3] arbeiten würde, aber die nächste Iteration würde die Daten mit dem timeStamp des nächsten Ereignisses überschreiben? Ich werde es versuchen und dich wissen lassen. – Lpaulson

+0

Ja, das ist richtig. –

+0

Spot auf! Ich hätte eine Weile nach dem gesucht. – Lpaulson