Sensor daten über UART verschicken (mit PIC)

OP #7135271
Lesenswert?

Hey zusammen. Ich habe grad ein kleines Problem.
Ich versuche die daten meines SCD30 CO2 Sensors in ein array zu 
speichern (via I2C an meinem PIC) und die daten dann über UART an mein 
Travos3 modul zuschicken.
Das gleiche Modul habe ich auch an meine PC angeschloßen und will die 
Werte dann auf HTerm lesen können.

Nur leider klappt es nicht so ganz, I2C funktioniert aber wenn ich die 
Daten dann schicken sehe ich nur Nuller auf HTerm.

Ich habe schon probiert nur gewissen Bytes zu schicken, wo der wirkliche 
Inhalt (laut Datenbaltt) drin ist. Funktioniert aber leider auch nicht.

Danke für euere Hilfe im vorraus.
Gast #7135279
Lesenswert?

Kannst Du einen festen Text, wie z.B. "Hallo Welt !" an HTerm schicken ?

Wenn nein, gelingt es ohne die Module dazwischen ?

P.S. : Es gibt hier kaum jemanden im Forum, der per Gedankenübertragung 
in Deinen Quelltext schauen kann.
OP #7135293
Lesenswert?

Ein Hello World kann ich an meine modul schicken und sehe es auch auf 
HTerm.

Das wär meine while loop;
Wieso ich diese Bytes gewählt hab zum schicken liegt im Anhang beim 
Datenblatt. (Seite 12)


        uint8_t data[3];
        data[0] = 0xC2;
        data[1] = 0x03;
        data[2] = 0x00;

        I2C1_WriteNBytes(0x61, data, 3);


        I2C1_ReadNBytes(0x61, i2c_payload, 19);



        UART5_Write(0x02);
        UART5_Write(0x00);
        UART5_Write(0x0C);



        UART5_Write(i2c_payload[1]);
        UART5_Write(i2c_payload[2]);
        UART5_Write(i2c_payload[4]);
        UART5_Write(i2c_payload[5]);
        UART5_Write(i2c_payload[7]);
        UART5_Write(i2c_payload[8]);
        UART5_Write(i2c_payload[10]);
        UART5_Write(i2c_payload[11]);
        UART5_Write(i2c_payload[13]);
        UART5_Write(i2c_payload[14]);
        UART5_Write(i2c_payload[16]);
        UART5_Write(i2c_payload[17]);

        uint8_t summe = 0;
        summe = summe ^ 0x02;
        summe = summe ^ 0x00;
        summe = summe ^ 0x0C;
        summe = summe ^ i2c_payload[3];
        summe = summe ^ i2c_payload[6];
        summe = summe ^ i2c_payload[9];
        summe = summe ^ i2c_payload[12];
        summe = summe ^ i2c_payload[15];
        summe = summe ^ i2c_payload[18];

        UART5_Write(summe);
#7135318
Lesenswert?

Leonidas T. schrieb:
> Verzeih aber kannst du mir das erklären.

Wenn ein Wert 0 sein soll, gibt es bei der Übertragung entweder den 
Byte-Wert 0, also 0x00, oder das Ascii-Zeichen für "0", das wäre 48 bzw. 
0x30 als Byte-Wert.

Wenn du deinen Messwert von "3" nun nicht als ASCII-Zeichen 51 (0x33) 
überträgst, sondern als Byte-Wert von 3 (0x03), dann zeigt dein Terminal 
dir keine 3 an, sondern irgendeinen Indikator dafür, dass ein 
Steuerzeichen "End of Text" gesendet wurde. Denn das hat den Byte-Wert 
3.

Um aus dem Wert "54.3" nun einen ASCII-String mit den entsprechenden 
Zeichen zu machen, gibt es ein paar Funktionen (printf und solche 
Späßchen)
OP #7135412
Lesenswert?

Mario M. schrieb:
> Leonidas T. schrieb:
>>         data[0] = 0xC2;
>>         data[1] = 0x03;
>>         data[2] = 0x00;
>>
>>         I2C1_WriteNBytes(0x61, data, 3);
>
> Kann nicht klappen. In der PDF ist die komplette Übertragung auf dem Bus
> zu sehen. Die I²C-Adresse wird aber bei I2C1_WriteNBytes extra
> übergeben, daher  darf nicht noch mal 0xC2 gesendet werden. 0xC2 ist bei
> I²C Schreiben an Adresse 0x61.

Also soll ich 0xC2 nicht schreiben und es probieren oder wie?
Verzeih ich habs nicht ganz verstanden
OP #7135461
Lesenswert?

Also am ende vom Datenblatt finde ich wie ich die werte in physik. Werte 
umwandel. Nur denk ich es ist am ende eine variable und ich kann die 
nicht über UART schicken.
Über UART kann ich nur Byte by Byte schicken. (Da spezielles format)
Gibts es eine Möglichkeit die variable in ein array aufzuteilen um es 
eben in bytes zu unterteilen?

Ich danke euch
Gast #7135480
Lesenswert?

Leonidas T. schrieb:
> Gibts es eine Möglichkeit die variable in ein array aufzuteilen um es
> eben in bytes zu unterteilen?

man verschiebt die einzelnen Bytes der größeren Variablen um die 
entsprechende Anzahl von Bits:
1
uint16_t word = 0xAABB;
2
uint8_t bytes[2] = {0};
3
bytes[0] = word >> 8;     // MSB
4
bytes[1] = word & 0x00FF; // LSB
Man könnte den "Berechnungen" noch ein Cast verpassen. Sollte aber nicht 
notwendig sein.

Solche Bitschubsereien sind Grundlagen...
#7135489
Lesenswert?

Leonidas T. schrieb:
> I2C1_ReadNBytes(0x61, i2c_payload, 19);
>
>         UART5_Write(0x02);
>         UART5_Write(0x00);
>         UART5_Write(0x0C);
>
>         UART5_Write(i2c_payload[1]);
>         UART5_Write(i2c_payload[2]);
>         UART5_Write(i2c_payload[4]);

Die Zahl der gelesenen Bytes sollte durch 3 teilbar sein (also 18 statt 
19), weil immer MSB, LSB, CRC gesendet werden. Außerdem beginnt 
i2c_payload bei Null, die Messwerte liegen also bei 0, 1 und 3, 4 usw.
OP #7135499
Lesenswert?

STK500-Besitzer schrieb:

> man verschiebt die einzelnen Bytes der größeren Variablen um die
> entsprechende Anzahl von Bits:
>
>
1
> uint16_t word = 0xAABB;
2
> uint8_t bytes[2] = {0};
3
> bytes[0] = word >> 8;     // MSB
4
> bytes[1] = word & 0x00FF; // LSB
5
>
> Man könnte den "Berechnungen" noch ein Cast verpassen. Sollte aber nicht
> notwendig sein.
>
> Solche Bitschubsereien sind Grundlagen...

Dankeschön das war sehr hilfreich, ich probiers aus und sag euch 
bescheid :)
OP #7135678
Lesenswert?

Ich komm leider nicht weiter, also im datenblatt steht folgendes:

float co2Concentration;
unsigned int tempU32;

unsigned char buffer[4];
buffer[0] = 0x43; // MMSB CO2
buffer[1] = 0xDB; // MLSB CO2
buffer[2] = 0x8C; // LMSB CO2
buffer[3] = 0x2E; // LLSB CO2

tempU32 = (unsigned int)((((unsigned int)buffer[0]) << 24) |
 (((unsigned int)buffer[1]) << 16) |
 (((unsigned int)buffer[2]) << 8) |
 ((unsigned int)buffer[3]));

co2Concentration = *(float*)&tempU32; // co2Concentration = 439.09f

Die sache ist nur, ich weiss nicht wie ich co2Concentration über UART 
verschicken soll, da ich nur byte by byte verschicken kann. ICh würde es 
gerne in ein array abspeichern. Was denkt ihr??
Gast #7135683
Lesenswert?

Leonidas T. schrieb:
> Ich komm leider nicht weiter, also im datenblatt steht folgendes:
>
> co2Concentration = *(float*)&tempU32; // co2Concentration = 439.09f
>
> Die sache ist nur, ich weiss nicht wie ich co2Concentration über UART
> verschicken soll, da ich nur byte by byte verschicken kann. ICh würde es
> gerne in ein array abspeichern. Was denkt ihr??

Bitte sprintf() (Library-Funktion, oder fprintf()) nachschlagen. 
Eventuell ein Buch benutzen (bei solchen Fragen reicht Kernighan & 
Ritchie aus).

Gruesse

Th.
#7135723
Lesenswert?

Leonidas T. schrieb:
> Die sache ist nur, ich weiss nicht wie ich co2Concentration über UART
> verschicken soll, da ich nur byte by byte verschicken kann.

Will man mehr als ein Byte übertragen, benötigt man ein Protokoll. Die 
UART kann nicht unterscheiden, welches Byte in einem Datenstrom welche 
Bedeutung hat.

Ein einfaches Protokoll ist eine Textzeile, die mit CR/LF abgeschlossen 
wird und nur Textzeichen enthält. Werte lassen sich leicht als Text mit 
printf ausgeben, bzw. mit scanf einlesen.

Binärprotokolle sind zwar kompakter, aber auch deutlich komplexer und 
nicht direkt lesbar.
OP #7135862
Lesenswert?

Mario M. schrieb:
> Der Sensor gibt drei Messwerte zurück: CO2-Gehalt, Feuchtigkeit und
> Temperatur. Diese werden als  Float-Werte mit einer Länge von jeweils 4
> Bytes übermittelt. Das Programmbeispiel zeigt, wie die 4 Bytes in eine
> Float-Variable kopiert werden.

Das ist sehr hilfreich, ich danke dir.
Kann dich das programmieren, also das es von alleine passiert.
Gast #7136541
Lesenswert?

Mario M. schrieb:
> Der Sensor gibt drei Messwerte zurück: CO2-Gehalt, Feuchtigkeit und
> Temperatur. Diese werden als  Float-Werte mit einer Länge von jeweils 4
> Bytes übermittelt. Das Programmbeispiel zeigt, wie die 4 Bytes in eine
> Float-Variable kopiert werden.

Sowas ist einigermaßen ungewöhnlich, denn Gleitkommaformate können 
unterschiedlich sein. Sowohl vom schieren Format her als auch in den 
dargestellten Wertigkeiten. Muß aber nicht. Auf alle Fälle ist es 
hilfreich, im PIC all das, was da vom Sensor kommt, zunächst in ein 
Format zu wandeln, mit dem die GK-Routinen des verwendeten Compilers 
zurecht kommen und dann zur Übertragung diese in Text zu konvertieren. 
Und das dann senden.

Ob das, was da in deinem Datenblatt als funktionale Konvertierroutine 
angesehen werden kann, ist deshalb fraglich. Nach meiner Erfahrung sind 
Audrücke, wo extensiv gecastet wird, recht fehleranfällig.

Versuche doch erstmal, die vom Sensor kommenden Bytes als Hexzahlen zu 
senden, etwa so:
1
 String_Out("CO2: ",toUART1);
2
 HexB_Out(Buffer[0],toUART1); Char_Out(',',toUART1);
3
 HexB_Out(Buffer[1],toUART1); Char_Out(',',toUART1);
4
 HexB_Out(Buffer[2],toUART1); Char_Out(',',toUART1);
5
 HexB_Out(Buffer[3],toUART1); Crlf_Out(toUART1);

W.S.
Gast #7136745
Lesenswert?

1
 String_Out("CO2: ",toUART1);
2
 HexB_Out(Buffer[0],toUART1); Char_Out(',',toUART1);
3
 HexB_Out(Buffer[1],toUART1); Char_Out(',',toUART1);
4
 HexB_Out(Buffer[2],toUART1); Char_Out(',',toUART1);
5
 HexB_Out(Buffer[3],toUART1); Crlf_Out(toUART1);

Daran erkennt man den Könner, der unbegabte Laie würde viel 
umständlicher
1
 printf("CO2: %02x,%02x,%02x,%02x\r\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
schreiben.

Da sieht man förmlich, wie viel eleganter die Nutzung eigener 
Ausgabefunktionen ist.

Schön, dass hier ein Fachmann und Könner zeigt, wie es richtig gemacht 
wird. Auch die Quelltextformatierung ist mit mehreren Statements in 
einer Zeile viel überschaubarer. Wie lange man wohl braucht, um diesen 
Level an Exzellenz zu erlangen?
Gast #7136765
Lesenswert?

Profibewunderer schrieb:
> Daran erkennt man den Könner,...

Nö, sondern man erkennt das Prinzip. Das ist alles.

Aber mal im Detail: Wenn jemand eine Ausgabefunktion benutzt, die neben 
den Zeigern auf 4 Bytes obendrein auch noch einen Formatstring benötigt 
und dieser von einem in der Firmware befindlichen Textinterpreter 
auseinandergenommen werden muß, um dann dort viermal die eigentlichen 
Konvertier- und Ausgabefunktionen aufzurufen, dann ist das für dich eine 
bessere Lösung? Und das in einem PIC (allerdings ohne detaillierte 
Bezeichnung) mit vermutlich nur wenig Programmspeicher?

Ich habe da so den Eindruck, daß deine Vorstellungskraft nicht über 
einen C-Quelltext hinausreicht.

W.S.
Gast #7136777
Lesenswert?

Das ist es ja, was ich an Profis wie Dir bewundere. Die rufen neun 
Funktionen nacheinander auf, und schwabulieren immer was davon, wie 
unendlich kompliziert das doch alles ist, was printf veranstaltet.
Bekommen die Geld für nicht genutzes Flash-ROM ihrer Controller zurück?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren