Merkkien lukeminen ja kirjoittaminen arduinoon


#1

Yritin tällaisella c++ -ohjelmalla kirjoittaa ja lukea merkkejä
usb-johdolla koneeseen liitetystä arduinosta. En millään keksi,
miten ohjelmaa pitäisi muokata, että saisi luetuksi edes yhden
syötetyn merkin.

Netistä on löytynyt vihjeitä siitä, että usb-johdolla liitetyn
arduinon vuonohjaus ei toimisi helposti yhdessä oman c++ -ohjelman
kanssa, mutta kai se jotenkin pitäisi saada toimimaan, koska
arduinon oma serial-ikkunakin näyttää toimivan.

Kokeiluohjelma on tehty Ubuntulla, ja käännöskomento oli

g++ seriatest01.cpp -o seriatest01 -std=c++0x -Wall -pedantic

Lyhyt arduino ohjelma on sitten tässä sen alla.

Keksisikö joku keinon, jolla voisi omalla ohjelmalla
lukea esim. päätteestä kirjoitettua merkkejä arduinolla
ja sitten tulostaa ne takaisin päätteelle.

// serialtest01.cpp 
#include <unistd.h>     // nukkuaika, mutta ei ehkä säikeille 
#include <fstream>      // tiedostoluku ja -kirjoitus 
#include <iostream>     // cout 
 
int main(int argc, char* argv[]) 
{   
if(argc < 2)  
    { std::cerr << "Usage: " << argv[0] << " port name eg. /dev/ttyUSB3" << std::endl; 
       exit(0); 
     }  
 std::string str2(std::string("stty -F ") + argv[1] + std::string(" sane raw -echo 9600") ); 
std::fstream fs; // arduino näkyy ohjelmalle tiedostona 
fs.open (argv[1], std::fstream::in | std::fstream::out); // avataan arduino-tiedosto 
system( str2.c_str() ); // stty -F /dev/ttyUSB3 sane raw -echo 9600 
 int i = 0;  // kierroslaskuri     
char c1 = 'w'; // luettva merkki 1, luetaan pääteikkunasta 
char c2 = 'z'; // luettava merkki 2, luetaan arduinosta 
 sleep(1);  // jotta arduino varmasti mukana? 
  while(i++ < 5 )    // yritetään 5 kertaa saada arduino lukemaan syötetty kirjain
    {  
      std::cout << "anna kirjain "; 
      std::cin >> c1; 
      fs << c1 << std::endl; // kirjoitetaan sarjatiedostoon eli arduinolle 
      sleep(1); // että arduino ehtii varmasti mukaan 
      fs >> c2;   // arduinosta luetaan merkki 
      fs.flush(); 
      std::cout << "arduinosta luettiin " << c2 << std::endl; 
      sleep(0.1); 
    } 
  fs.close();  // lisätty varmuuden vuoksi 
} 

Tässä on arduino-ohjelma, joka yrittää aina lukea merkin, kun se on saatavilla Serialista.

// arduino-ohjelma
char ibuf[80] = "xxxx\n"; // tila luetuille merkeille 
 void setup() 
{ Serial.begin(9600); 
}
 
int i = 0; // käytetään puskurin lukemisen pituusrajana 

void loop() 
{ int n = Serial.available();  
  if(n > 0  && i < 15) 
  { ibuf[i++] = Serial.read(); // i on vian pituusrajoitus tässä 
     n--; 
  } 
  Serial.print(ibuf);  
  Serial.flush();  // flush, ettei jäisi minnekään välipuskureihin
}

#2

include-rivit näköjään kopioituivat vähän erikoisesti, mutta liitettävät ovat
unistd.h
fstream.h
iostream.h
tavallisen risuaidan kanssa ja pienempi kuin - ja suurempi kuin - merkkien välissä


#3

Korjasin vähän muotoiluja tosta, Discourse käyttää Markdownia muotoiluun ja on siinä editorin toolbarissakin valmiiksi “preformatted” -nappi.

Tämä esimerkiksi on toimiva pätkä joka lukee rivejä sarjaportista ja sitten kutsuu eri moduulien parsereita jotka joko reagoivat tai ovat reagoimatta komentoon (noin kokonaisuutena kyseessä on kilke jolla voi D-BUS:in yli käskyttää Arduinoa ja toisaalta saada eventtejä esim input-muutoksista, joskus kun joudan porttaan sen 0MQ:lle)

Itse C++ kilkkeeseen en ota kantaa. Bootatessaan se Arduino antaa sarjaporttiin kaikenmoista roskaa joten suosittelen lämpimästi että setup() lähettää jonkun useampimerkkisen ASCII-tunnisteen jota sarjaporttia vahtiva kilke voi etsiä ennenkuin yrittää ruveta oikeasti parsimaan mitään muuta linjalta tulevaa dataa (on myös ihan kätevä oikean laudan tunnistamiseen jos niitä on useampi kiinni kun USB enumerointijärjestys vaikuttaa siihen minkä device-pathin/com-portin numeron sattuvat saamaan…

Edit: Ja tossa olis esimerkki tuotannossa (sittemmin taitaa kyllä olla tota päivitetty, pitänee tallentaa tuorein generoitu githubiin asti…) olevasta arDuBUS sketchistä

Eli lähetä tyhjä rivi ekaksi ja sitten ne tunnisteet joita sarjaporttia kuunteleva kilke etsii.