W poprzednim tekście o niewielkim generatorze przebiegów prostokątnych pisałem o możliwości konfigurowania go przez port szeregowy. Pokazałem, jak to można zrobić przez konsolę szeregową, np. Putty. Oczywiście nic nie stoi na przeszkodzie, żeby sterować nim z… Arduino.
Co więcej – GND, RX i TX generatora można wpiąć bezpośrednio do gniazd portów Arduino – GND, D13 i D12. Pozostaje podłączyć zasilanie VIN Arduino do VIN+ generatora… i gotowe!
Arduino może sterować generatorem. Najpierw, do nowego szkicu dodajcie bibliotekę SoftwareSerial. Zainicjalizujcie port szeregowy – zmienna „ss”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <SoftwareSerial.h> #define TX 13 #define RX 12 //Create serial port SoftwareSerial ss(RX, TX); void setup() { Serial.begin(9600); ss.begin(9600); } void loop(){ //... } |
Zwróćcie uwagę:
- Oprócz standardowego portu szeregowego (sprzętowego, „Serial”) – tworzę dodatkowy „ss”, obsługiwany programowo; port sprzętowy „Serial” będzie mi służył do wysyłania statusu po kabu USB do połączenia,
- Nowy port „ss” podpięty jest pod piny D12 (RX) i D13 (TX),
- Obydwa porty ustawiam na szybkość 9600.
Teraz dodam funkcję wysyłającą dane do generatora i sprawdzającą jego odpowiedź:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//Send to generator bool sendToGen(SoftwareSerial s, String toSend) { Serial.print("\nSending: "); s.listen(); for (int _i = 0; _i < toSend.length(); _i++) { s.write( toSend[ _i] ); delay(100); Serial.print( toSend[ _i] ); int _res = s.peek(); //Letter F: FAIL if ( _res == 70 ) { Serial.println("\nSend FAIL"); return false; } } Serial.println("\nSent"); return true; } |
Zwróćcie uwagę:
- s.listen() jest konieczne do odbierania danych z portu programowego,
- niewielkie opóźnienie delay(100) zapewnia, że generator nadąży z odbieraniem danych,
- po wysłaniu literki polecenia sprawdzam czy generator czegoś nie zwrócił (s.peek()),
- jeżeli na linii pojawi się literka „F” (początek wyrazu FAIL) – zwracam „false” – gdyż wysyłanie zakończyło się porażką,
- w innym przypadku zwracam „true” – sukces.
W loop() można dodać kilka testów:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//... //Just to test void loop() { //Should finish with error sendToGen(ss, "S3F100T"); delay(2000); sendToGen(ss, "S1F200T"); delay(2000); sendToGen(ss, "S1F300T"); delay(2000); } |
Pierwsze polecenie („S3F100T”) powinno skończyć się porażką – generator nie ma trzech kanałów.
Chociaż w ostatecznej implementacji lepiej by było np.:
1 2 3 4 5 6 7 8 |
int _tryMe = 3; bool _result; while ( !( _result = sendToGen(ss, "S1F200T") ) && _tryMe-- > 0){ delay(250); } if( !_result ){ ///call fail } |
Powyższy kod próbuje wysłać komendę ustawiającą 200Hz na wyjściu PWM1. Robi to do uzyskania poprawnego wyniku lub 3 razy.
Cały kod:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <SoftwareSerial.h> #define TX 13 #define RX 12 //Create serial port SoftwareSerial ss(RX, TX); void setup() { Serial.begin(9600); ss.begin(9600); } //Send to generator bool sendToGen(SoftwareSerial s, String toSend) { Serial.print("\nSending: "); s.listen(); for (int _i = 0; _i < toSend.length(); _i++) { s.write( toSend[ _i] ); delay(100); Serial.print( toSend[ _i] ); int _res = s.peek(); //Letter F: FAIL if ( _res == 70 ) { Serial.println("\nSend FAIL"); return false; } } Serial.println("\nSent"); return true; } //Just to test void loop() { sendToGen(ss, "S3F100T"); delay(2000); sendToGen(ss, "S1F200T"); delay(2000); sendToGen(ss, "S1F300T"); delay(2000); } |