Jak wysyłać numery do Arduino UNO przez Python 3 i szeregowy moduł

9

Jestem nowy w Arduino (i ogólnie programowaniu komputerowym), więc przepraszam, jeśli to pytanie wygląda głupio.

Po skonfigurowaniu podstawowego połączenia arduino-LED mam problemy z wysyłaniem INTEGERÓW do arduino przez port szeregowy. Mogę łatwo wysyłać znaki, takie jak „m”, „o” itd. Jednak jeśli wyślę numer, wygląda na to, że po prostu go nie dostanie.

Oto kod Arduino, najlepiej powinien uzyskać wartość z portu USB przez python lub monitor szeregowy, a następnie dostosować jasność diody LED zgodnie z wartością. (wartość musi mieścić się w zakresie [0,255]).

UWAGA: Używam ARDUINO UNO i PYTHON 3

// --------------------------

int LED = 10;
int number;

void setup(){

pinMode(LED,OUTPUT);
Serial.begin(9600);
}

void loop(){

number = Serial.read();
Serial.print(number);
Serial.print('\n');
if(number == -1){
number = 0;
}

else if(number > 255){

number = 255;

}

else if(number < 0){

number = 0;
}

analogWrite(LED,number);
delay(1000);
}

Jednak gdy wprowadzam wartość do portu szeregowego lub przez Python, na przykład 0, daje mi 48 jako odpowiedź (co, co ciekawe, jest kodem ASCII dla 0!) I zapala diodę, co nie powinno się zdarzyć, ponieważ przy 0 dioda LED powinna zgasnąć !! Coś mi brakuje, ale nie mogę znaleźć ... Czy mógłbyś mi powiedzieć, co jest nie tak?

Oto kod, którego używam w Pythonie:

import serial
import time
try:
    arduino = serial.Serial(port,speed)
    time.sleep(2)
    print("Connection to " + port + " established succesfully!\n")
except Exception as e:
    print(e)

#Note: for characters such as 'a' I set data = b'a' to convert the data in bytes
#However the same thing does not work with numbers...
data = 0
data = arduino.write(valueToWrite)
time.sleep(2)
arduino.close()

co robię źle lub nieporozumienie? Dziękuję Ci.

mickkk
źródło
1
Spróbujarduino.write(chr(valueToWrite))
Gerben,
To rozwiązanie nie działa nawet dla znaków. Ponadto, jeśli chodzi o znaki, działa dobrze, wysyłając je jako bajty, takie jak: b'm '. W każdym razie dzięki za odpowiedź.
mickkk

Odpowiedzi:

6

Analiza na Arduino może być powolna i czasochłonna (co jest złe, jeśli używasz wstępnego skalowania zegara lub wykonujesz zadania o krytycznym czasie), więc zróbmy to w Pythonie.

Problem polega na tym, że wysyłasz liczby jako ASCII, podczas gdy musisz wysyłać je jako surowe dane binarne. To jest, gdzie structprzychodzi.

3>> import struct
3>> print(struct.pack('>B', 0))
b'\x00'
3>> print(struct.pack('>B', 255))
b'\xff'
3>> print(struct.pack('>2B', 255, 0))
b'\xff\x00'
3>> print(struct.pack('>H', 9000))
b'#('

Więc tak naprawdę chcesz:

data = arduino.write(struct.pack('>B', valueToWrite))

lub coś w tym rodzaju.

Ignacio Vazquez-Abrams
źródło
Dziękuję Ci bardzo! Właśnie tego szukałem!
mickkk
Pomimo tego, co mówi pusty szary pole komentarza, zamierzam podziękować! Próbowałem napisać strumień bitów (plik programu .bin FPGA) do układu flash SPI przy użyciu Teensy 3.2 z Arduino jako interfejsem PC -> flash, i to było kluczowe, aby działał na komputerze.
KyranF,
1

Serial.read()czyta tylko JEDEN znak z portu szeregowego i zwraca jego wartość ASCII, co wyjaśnia 48otrzymaną wartość.

Aby odczytać pełny numer, masz 2 opcje:

  1. Użyj, Serial.parseInt()która odczytuje tyle znaków, ile potrzeba i wykonuje konwersję przed zwróceniem odczytanego numeru jako int. Więcej informacji znajdziesz tutaj.
  2. Czytasz eachn postać w pętli (z Serial.read()) aż do ostatniego, umieścić każdy charcater wczytywane do bufora ( chararray), a następnie przekonwertować ciąg wynikowy do numeru ze standardową funkcją C atoi.

Oczywiście pierwsza opcja jest najłatwiejsza, ale wróci, 0jeśli po upływie limitu czasu nic nie zostanie odczytane (konfigurowalne za pomocą Serial.setTimeout()).

jfpoilpret
źródło
Ta odpowiedź nie była dokładnie tym, o co prosiłem, jednak była bardzo przydatna i będę jej używać! Bardzo dziękuję za pomoc!
mickkk