Hallo,
ich versuche über Python die serielle Schnittstelle anzusprechen und
versende da das Byte "1". Im µC überprüfe ich dann, ob "1" angekommen
ist und gebe dann einen Text aus, wenn die angekommenen Daten nicht "1"
entsprechen, gebe ich die angekommenen Daten aus. Seltsamerweise kommt
bei meinem Python-Programm immer 49\n an.
Könnte mir da jemand erläutern, warum dass so ist und wieso anscheinend
beim Mikrocontroller nicht "1" ankommt? Muss ich den gelesenen Text noch
irgendwie umwandeln?
Python:
Vermutlich sagst du Python mit "1", dass es sich um das ASCII-Zeichen 1
handelt. Das kleine b davor soll vermutlich aussagen, dass die 1 binär
anzusehen ist. Vielleicht geht es ohne Anführungszeichen?
Max M. schrieb:> Danke, so gehts einfacher:> uint8_t val = uart_getc();> char result[3] = {val};> strcat(result,"\n");> uart_puts(result);
was soll denn der Unsinn.
damit sendest du Binär im Zusammenhang mit \n macht das aber wenig sinn.
Was ist wenn du mal eine 13 zurück sendest? Oder noch spannenden wenn
mal eine 0 gesendet werden soll.
Peter II schrieb:> damit sendest du Binär im Zusammenhang mit \n macht das aber wenig sinn.
Somit erkennt Python, wann der gesendete Text zu Ende ist.
Peter II schrieb:> Was ist wenn du mal eine 13 zurück sendest?
Dann kommt das dabei raus :(
Max M. schrieb:> Somit erkennt Python, wann der gesendete Text zu Ende ist.
genau das führt aber zu Problemen, wenn du 13 oder eine 0 sendest. Du
kannst nicht einfach Binär und Ascii mischen und hoffen das geht
irgendwie.
Sende zahlen als Ascii also eine 1 als 49 (oder '1') und schon kannst du
sauber mit \n arbeiten.
Peter II schrieb:> Sende zahlen als Ascii also eine 1 als 49 (oder '1') und schon kannst du> sauber mit \n arbeiten.
Da sagt mir Python dann, dass es einen int erwartet (wenn ich einen Int
übergebe, wird mir gesagt: 'int' object is not iterable).
Max M. schrieb:> Da sagt mir Python dann, dass es einen int erwartet (wenn ich einen Int> übergebe, wird mir gesagt, dass Integer nicht iterable ist).
ser.write("1") tut es nicht?
Felix Adam schrieb:> Vermutlich sagst du Python mit "1", dass es sich um das ASCII-Zeichen 1> handelt. Das kleine b davor soll vermutlich aussagen, dass die 1 binär> anzusehen ist. Vielleicht geht es ohne Anführungszeichen?
Nein. In nicht zu alten Python-Versionen denotiert der Prefix b in
Literals, daß ein Bytestring gemeint ist, nicht ein Textstring. PySerial
sollte beides können. Und dass ser.write(b'1') oder ser.write('1') "an
integer is required" produziert, glaube ich nicht.
Das "Problem", dass hier auftritt, beruht auf den unterschieden zwischen
Python 2.x und Python 3.x. In Python 3 geht das aber auch voll
entspannt, wenn man das Zeichen vor dem versenden in den richtigen Typ
castet.
Kaj schrieb:> In Python 3 geht das aber auch voll> entspannt, wenn man das Zeichen vor dem versenden in den richtigen Typ> castet.
Magst du da ein Beispiel geben, wie ich die
1
13
casten muss?
Sven B. schrieb:> mach mal> ser.write(bytes([13]))
Läuft! Danke
Ich würde in Python das Wort "cast" nicht verwenden, das passt
eigentlich nicht.
Du musst die 13 in ein Bytearray mit einem Element umwandeln. Das machst
du genau so wie ich es geschrieben habe, du machst eine Liste mit einem
Element, also [13], und konvertierst die dann in ein Byte Array, also
bytes([13]). Jeder Eintrag der Liste wird zu einem Byte.
Noch mal ein weiteres Problem mit UART. Nun versuche ich den analogen
Wert eines Temperatursensors (LM35DZ) auszulesen und danach über UART
auszugeben:
1
#define F_CPU 16000000L //16 MHz
2
3
#include<avr/io.h>
4
#include<stdint.h>
5
#include<stdlib.h>
6
#include<util/delay.h>
7
#include<string.h>
8
9
#define ADC_PIN 0
10
11
#define LED_PIN PORTB5
12
13
#define ADC_THRESHOLD 512
14
15
voiduart_puts(char*s)
16
{
17
while(*s)
18
if(UCSR0A&(1<<UDRE0))
19
UDR0=*s++;
20
}
21
22
uint16_tadc_read(uint8_tadcx){
23
ADMUX&=0xf0;
24
ADMUX|=adcx;
25
26
/* This starts the conversion. */
27
ADCSRA|=_BV(ADSC);
28
29
while((ADCSRA&_BV(ADSC)));
30
31
returnADC;
32
}
33
34
intmain(void){
35
36
ADCSRA|=_BV(ADEN);
37
38
DDRB|=_BV(LED_PIN);
39
40
while(true){
41
uint16_tadcValue=adc_read(ADC_PIN);
42
if(adcValue>ADC_THRESHOLD)
43
PORTB|=(1<<LED_PIN);
44
else
45
PORTB&=~(1<<LED_PIN);
46
charresult[30];
47
itoa(adcValue,result,16);
48
strcat(result,"\n\r");
49
uart_puts(result);
50
_delay_ms(500);
51
}
52
}
allerdings kommt im Terminal-Window von Atmel Studio nur komisches
Kauderwelsch an:
Max M. schrieb:> allerdings kommt im Terminal-Window von Atmel Studio nur komisches> Kauderwelsch an:> ËËÕÿÿÿÿÿÿ¥¥¥¥¥¥¥¶øË
dann werden wohl die Schnittstellen Parameter nicht stimmen.
Baudrate, Bitzahl, Parität, Stoppits
Peter II schrieb:> dann werden wohl die Schnittstellen Parameter nicht stimmen.
Danke, das war der nötige Hinweis, dass ich die uart_init() - Funktion
vergessen habe, wie dumm von mir:
1
#define F_CPU 16000000L //16 MHz
2
3
#define BAUD 9600UL
4
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
5
6
#include<avr/io.h>
7
#include<stdint.h>
8
#include<stdlib.h>
9
#include<util/delay.h>
10
#include<string.h>
11
#include<util/setbaud.h>
12
13
#define ADC_PIN 0
14
15
#define LED_PIN PORTB5
16
17
#define ADC_THRESHOLD 512
18
19
voiduart_puts(char*s)
20
{
21
while(*s)
22
if(UCSR0A&(1<<UDRE0))
23
UDR0=*s++;
24
}
25
26
voiduart_init(void)
27
{
28
UBRR0=UBRR_VAL;
29
UCSR0B|=(1<<TXEN0);
30
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
31
}
32
33
uint16_tadc_read(uint8_tadcx){
34
ADMUX&=0xf0;
35
ADMUX|=adcx;
36
37
/* This starts the conversion. */
38
ADCSRA|=_BV(ADSC);
39
40
while((ADCSRA&_BV(ADSC)));
41
42
returnADC;
43
}
44
45
intmain(void){
46
47
ADCSRA|=_BV(ADEN);
48
49
DDRB|=_BV(LED_PIN);
50
51
uart_init();
52
53
while(true){
54
uint16_tadcValue=adc_read(ADC_PIN);
55
if(adcValue>ADC_THRESHOLD)
56
PORTB|=(1<<LED_PIN);
57
else
58
PORTB&=~(1<<LED_PIN);
59
charresult[30];
60
itoa(adcValue,result,10);
61
strcat(result,"\n");
62
uart_puts(result);
63
_delay_ms(500);
64
}
65
}
Jetzt bekomm ich als Wert 1023. Aber wenn ich meinen Finger an den
Temperatursensor halte, ändert sich das nicht?
Okay, wenn ich den Strom abstecke, ändert sich auch nichts ^^
Wie sieht denn die Beschaltung des AREF-Pins aus?
Hängt da nur der übliche Kondensator dran oder auch eine
Referenzspannung (z.B. Vcc)?
Wenn keine extra Referencspannung angeschlossen ist, mußt Du noch die
REFSx Bits im ADMUX Register korrekt setzen.
fb schrieb:> AREF-Pins
Ähm, damit kann ich leider gar nichts anfangen. Auch im Datenblatt finde
ich nichts dazu.
fb schrieb:> Wenn keine extra Referencspannung angeschlossen ist,
Meinst du am Temperatursensor? Der ist mit GND und 5V verbunden.
Der Konstruktor der Serial-Klasse wirft bereits eine Exception, wenn er
die entsprechende Schnettstille nicht öffnen kann. Wenn der Konstruktor
erfolgreich war, also keine Exception geworfen hat, ist es nicht nötig,
das erfolgreiche Öffnen mit isOpen() zu überprüfen -- zumal Dein "try:
ser.isOpen()" das Ergebnis ins Nirvana schreibt und deswegen genau gar
nichts tut. Richtig müßte es heißen "try: assert ser.isOpen() == True".
Auch die Überprüfung vor der while()-Schleife ist unsinnig: da prüfst Du
einmal, ob das Ding geöffnet wurde, und loopst dann ewig darauf herum.
Wenn die Schnittstelle während der Schleife entfernt wird, zum Beispiel
weil der USB-Serial-Adapter abgezogen wurde, nutzt Dir das an der Stelle
überhaupt gar nichts. Eine alternative könnte sein, ser.isOpen() als
Schleifenbedingung zu benutzen oder ein "assert ser.isOpen() == True"
innerhalb der Schleife zu benutzen -- TIMTOWTDI.
Und um nebenbei noch Deine Frage zu beantworten: "49" ist der ASCII-Code
für die Ziffer "1". Um eine "1" zu schicken, möchtest Du keinen binären
String (b"1"), sondern einfach die Zahl 1 (int(1)) benutzen.
Liebe Grüße,
Karl