Generare, Elaborare e Trasmettere Codice RS232

Buongiorno a tutti!

Grazie per il vostro tempo che dedicherete a leggere…
Non sono disperato, di più :frowning:

Partiamo dal presupposto che non sono ingegnere, e non sono studiato in materia informatica, però è già qualche anno che smanetto su arduino, e riesco bene o male in quello che voglio fare…Questa volta no.

Premessa del mio problema, orecchie ben attente :o :o :

-Ho 2 modem wifi, tra questi due (uno Access Point e uno Client) viene trasmesso un segnale video. Funziona.

-Questi due modem permettono la trasmissione/ricezione di un segnale aggiuntivo, su porta rs232. Funziona, riesco a far comunicare i due apparecchi tramite pc e putty, utilizzo anche un adattatore usb/rs232.

-Ho poi a disposizione un apparecchio (con potenziometri e switch) che spara in uscita su un cavo (con protocollo PPM) tutti i valori. Con l’arduino uno funziona, riesco a leggere i valori correttamente e vederli sullo schermo grazie al comando Serial.print.

Arriviamo dunque al problema vero e proprio:

-Elaborare i valori in uscita dall’apparecchio, metterli dentro al convertitore rs232.

Sicuramente ci sono 6 potenziometri, ognuno di essi crea 1000 valori differenti, che già riesco a leggerli, però non ho idee su come strutturare il codice affinchè ogni valore corrisponda ad un codice binario diverso, ovviamente non posso creare 6000 if… vi immaginate? lol

if((x<1000)&&(x>999)){
divento_matto();
}

Dopo di chè non ho ancora capito se il bit di start ed il bit di stop della comunicazione viene generato dal convertitore (MAX232) o se dovrei generare anche quello con l’arduino?

Per schiarire le idee e dare un nome alle cose…il progetto consiste nel telecomandare una webcam (montata su dei servomotori, il movimento è su 4 assi) a distanza con una vecchia radio da modellismo.

Prova a spiegarti meglio
Io ho capito cosi:
Hai un coso con 4 manopole, che da fuori in ppm 4 comandi per 4 servo
Tu intercetti con una UNO questi comandi e riesci a vederli su monitor seriale
Il problema è codificarli e trasmetterli su un canale seriale, per poi riceverli e decodificarli
Ho capito?

Hai provato a scrivere sulla seriale collegata al convertitore il valore tal quale con il metodo write anziché usare la print?

Grazie per le risposte. Mi fa piacere aver la possibilità di confrontarmi.

Standardoil:
Prova a spiegarti meglio
Io ho capito cosi:
Hai un coso con 4 manopole, che da fuori in ppm 4 comandi per 4 servo
Tu intercetti con una UNO questi comandi e riesci a vederli su monitor seriale
Il problema è codificarli e trasmetterli su un canale seriale, per poi riceverli e decodificarli
Ho capito?

Il coso è un radiocomando, che da fuori in PPM 10 canali, tra quei 10, 4 sono destinati a controllare 4 servo.
Ogni manopola, o potenziometro, quindi controlla 1 servo.
Il mio problema è esattamente quello, codificare il segnale e farlo uscire dall'arduino sul seriale.

Il problema del riceverlo e decodificarlo arriverà dopo. :slight_smile:

fabpolli:
Hai provato a scrivere sulla seriale collegata al convertitore il valore tal quale con il metodo write anziché usare la print?

Al momento i sistemi sono separati, ho l'arduino che legge il ppm, e (separato appunto) 2 computer dove faccio comunicare i due modem, sul pc faccio girare putty, riesco a scrivere, inviare e leggere da entrambi i pc..
Il serial.print lo sto utilizzando nello sketch caricato sull'arduino uno, leggo i valori ppm e li metto sul monitor seriale dell'IDE.

Grazie

Potresti fare un esempio con solo tre valori di cosa vorresti fare

if((x<1000)&&(x>999))
{
  ...qui cosa faresti???
}
if((x<999)&&(x>998))
{
  ..e qui???
}

Invece, per me, potresti postare il codice attuale?
Come interfacceresti arduino alla seriale, presumo sia una rs232f
Hai un traslatore di livello ttl-rs232?

fabpolli:
Potresti fare un esempio con solo tre valori di cosa vorresti fare

if((x<1000)&&(x>999))

{
 …qui cosa faresti???
}
if((x<999)&&(x>998))
{
 …e qui???
}

Siccome devo controllare dei servomotori, ogni tot step del potenziometro corrisponderanno ad una determinata inclinazione appunto del servo :slight_smile:
Però mi sto preoccupando della traduzione del dato in modo che l’rs232 me lo trasmetta (cioè binario?), dopo di chè sul sistema che gestisce i servi posso anche mettere un altro arduino che traduca ed elabori il dato.

Quindi, cosa farei?

Master/Trasmettitore

if((x<1000)&&(x>999))
{
 //Scrivo la x in rs232 
}
if((x<999)&&(x>998))
{
  //Scrivo la x in rs232
}

Slave/Ricevitore

//Ricevo il codice rs232 che lo chiamo y
[...]
//Traduco y e a quel punto posso fare gli if
if((y<1000)&&(y>999))
{
 //Scrivo uscita servo a 50 gradi 
}
if((y<999)&&(y>998))
{
  //Scrivo uscita servo a 60 gradi 
}

appunto quello che sostengo dall'inizio se fai la trasmissione del valore 9 con la print viene convertito in carattere ed inviata la codifica di 9 come carattere, se usi la write invii il VALORE 9 rendendo innutile la serie di if ovvero

Serial1.write(x);

Sempre che, come chiesto da StandardOil, tu alla seriale abbia attaccato un convertitore di livelli pena il non funzionamento e/o la distruzione dei pin

E ricevendo un valore su seriale non ti servono neanche lato ricevitore gli if per il solito principio

Standardoil:
Invece, per me, potresti postare il codice attuale?
Come interfacceresti arduino alla seriale, presumo sia una rs232f
Hai un traslatore di livello ttl-rs232?

Attualmente non ho un codice dal momento che l'arduino è impegnato solo a leggere il ppm.

Il traslatore di livello me lo sono procurato, fa appunto il passaggio dalle tensioni TTL a quelle della RS232, questo per intenderci LINK
E' un progetto ancora agli inizi.. mi stavo confrontatndo per chiarirmi le idee, perchè girovagando qualche giorno sul web ho trovato molte info ma non così chiare..

Grazie

Rom_Maker:
Attualmente non ho un codice dal momento che l'arduino è impegnato solo a leggere il ppm.

infatti
Posta il codice che legge il ppm

fabpolli:
appunto quello che sostengo dall’inizio se fai la trasmissione del valore 9 con la print viene convertito in carattere ed inviata la codifica di 9 come carattere, se usi la write invii il VALORE 9 rendendo innutile la serie di if ovvero

Serial1.write(x);

Sempre che, come chiesto da StandardOil, tu alla seriale abbia attaccato un convertitore di livelli pena il non funzionamento e/o la distruzione dei pin

Scusami, non so se ho capito bene…
Un carattere corrispondende a ogni canale quindi 10 caratteri? Oppure mandare direttamente direttamente il ppm letto da arduino quindi 4 caratteri per 10 canali?

Grazie

Standardoil:
infatti
Posta il codice che legge il ppm

Si, eccolo.

Grazie

unsigned long int ft, lt, x, tfail;
int ch, chx[9][13];

const int idx   = 10;
const int total = 11;
const int val   = 12;

void setup() {
  Serial.begin(9600);
  ft=0; lt=0; x=0; tfail=0; ch=0;
  for (int i=0; i<9; i++) {
    for (int j=0; j<13; j++) {
      chx[i][j]=0;
    }
  }
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), decodePPM, FALLING);
}

void loop() {
  if ((millis()-tfail)>500) {
    Serial.println("Disconnect");
  } else {
    Serial.print(chx[0][val]);Serial.print("\t");
    Serial.print(chx[1][val]);Serial.print("\t");
    Serial.print(chx[2][val]);Serial.print("\t");
    Serial.print(chx[3][val]);Serial.print("\t");
    Serial.print(chx[4][val]);Serial.print("\t"); 
    Serial.print(chx[5][val]);Serial.print("\t");
    Serial.print(chx[6][val]);Serial.print("\t");
    Serial.print(chx[7][val]);Serial.print("\t");
    Serial.println(chx[8][val]);    
  }
}

void decodePPM() {  
  lt    = micros();
  tfail = millis();
  x     = lt-ft;
  ft    = lt;
  if (x>3000) {
    ch          = 0;
    chx[0][val] = x;
  } else {
    ch+=1;
    int indx       = chx[ch][idx];
    chx[ch][total] = chx[ch][total] - chx[ch][indx];
    chx[ch][indx]  = x;
    chx[ch][total] = chx[ch][total] + chx[ch][indx];
    chx[ch][idx]   = chx[ch][idx] + 1;
    if (chx[ch][idx]>9) {
      chx[ch][idx] = 0;
    }
    chx[ch][val] = chx[ch][total]/10;
  }
}

Rom_Maker:
Scusami, non so se ho capito bene..
Un carattere corrispondende a ogni canale quindi 10 caratteri? Oppure mandare direttamente direttamente il ppm letto da arduino quindi 4 caratteri per 10 canali?

Dipende dal tuo protocollo di trasmissione ovvero il ricevente cose si aspetta? Se ad esempio si aspetta valore1,valore2,valore3,...,valoreN
Puoi pensare di fare

Serial.write(x);
Serial.print(',');

Se tra un valore ed un altro aspetta la tabulazione

Serial.write(x);
Serial.print('\t');

Se aspetta un terminatore tipo FF

Serial.write(x[i]);
Serial.write(0xFF);

e così via, insomma dipende dal ricevente.
Se ancora devi costruire il programma sia del trasmettitore che del ricevitore sta a te definirti un protocollo da seguire e usarlo.

fabpolli:
Dipende dal tuo protocollo di trasmissione ovvero il ricevente cose si aspetta? Se ad esempio si aspetta valore1,valore2,valore3,...,valoreN
Puoi pensare di fare
[...]

Ti ringrazio per il tempo dedicato.
Ora è chiaro.

Dal punto di vista del cablaggio come mi devo comportare invece?
Al momento ho solo un pin analogico occupato dal ppm.
:slight_smile:

ho provato a dare un occhio al tuo codice:

unsigned long int ft, lt, x, tfail; // io le metterei volatile, pero' se funziona...
int ch, chx[9][13];

const int idx   = 10;
const int total = 11;
const int val   = 12;
#include <SoftwareSerial.h>
#define RX 3
#define TX 4
// i piedini per la softserial

#define START '#' //inizio trasmissione
#define STOP '*' // fine trasmissione

SoftwareSerial RS232(RX, TX);
void setup()
{
    Serial.begin(9600);
    RS232.begin(9600);
    // ft=0; lt=0; x=0; tfail=0; ch=0; non serve variabili globali sono a zero di loro
    // for (int i=0; i<9; i++) {
    //   for (int j=0; j<13; j++) {
    //     chx[i][j]=0;
    //   }
    // }
    pinMode(2, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(2), decodePPM, FALLING);
}

void loop()
{
    if ((millis() - tfail) > 500)
    {
        Serial.println("Disconnect");
    }
    else
    {
        Serial.print(chx[0][val]); Serial.print("\t");
        Serial.print(chx[1][val]); Serial.print("\t");
        Serial.print(chx[2][val]); Serial.print("\t");
        Serial.print(chx[3][val]); Serial.print("\t");
        Serial.print(chx[4][val]); Serial.print("\t");
        Serial.print(chx[5][val]); Serial.print("\t");
        Serial.print(chx[6][val]); Serial.print("\t");
        Serial.print(chx[7][val]); Serial.print("\t");
        Serial.println(chx[8][val]);
        // mi sembra bello confuso
        // comunque qui abbiamo i valori appena stampati
        // ok
        // trasmettiamoli
        // sono int, quindi non possiamo fare write brutale brutale
        // io consiglio sempre di trasmettere in ASCII, perchè è più facile "capire" se ci sono problemi
        // sequenza di trasmissione:
        // un carattere di start
        // un indicatore di canale
        // il primo canale
        // un indicatore di canale
        // il secondo canale.....
        // al termine mettiamo un carattere di stop
        RS232.print(START);

        for (byte i = 0; i < 9; i++)
        {
            RS232.write('A' + i); // separatore e' la lettera che identifica il canale A=0, B=1.....
            RS232.print(chx[i][val]);
            // stampato
        }

        RS232.print(STOP);
    }
}

void decodePPM()
{
    lt    = micros();
    tfail = millis();
    x     = lt - ft;
    ft    = lt;

    if (x > 3000)
    {
        ch          = 0;
        chx[0][val] = x;
    }
    else
    {
        ch += 1;
        int indx       = chx[ch][idx];
        chx[ch][total] = chx[ch][total] - chx[ch][indx];
        chx[ch][indx]  = x;
        chx[ch][total] = chx[ch][total] + chx[ch][indx];
        chx[ch][idx]   = chx[ch][idx] + 1;

        if (chx[ch][idx] > 9)
        {
            chx[ch][idx] = 0;
        }

        chx[ch][val] = chx[ch][total] / 10;
    }
}

vedi se ti ritrovi, tra poco attacca montalbano, casomai domani se ne parla

Standardoil:
ho provato a dare un occhio al tuo codice:

unsigned long int ft, lt, x, tfail; // io le metterei volatile, pero' se funziona...

int ch, chx[9][13];

const int idx  = 10;
const int total = 11;
const int val  = 12;
#include <SoftwareSerial.h>
#define RX 3
#define TX 4
// i piedini per la softserial

#define START ‘#’ //inizio trasmissione
#define STOP ‘*’ // fine trasmissione

SoftwareSerial RS232(RX, TX);
void setup()
{
    Serial.begin(9600);
    RS232.begin(9600);
    // ft=0; lt=0; x=0; tfail=0; ch=0; non serve variabili globali sono a zero di loro
    // for (int i=0; i<9; i++) {
    //  for (int j=0; j<13; j++) {
    //    chx[i][j]=0;
    //  }
    // }
    pinMode(2, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(2), decodePPM, FALLING);
}

void loop()
{
    if ((millis() - tfail) > 500)
    {
        Serial.println(“Disconnect”);
    }
    else
    {
        Serial.print(chx[0][val]); Serial.print("\t");
        Serial.print(chx[1][val]); Serial.print("\t");
        Serial.print(chx[2][val]); Serial.print("\t");
        Serial.print(chx[3][val]); Serial.print("\t");
        Serial.print(chx[4][val]); Serial.print("\t");
        Serial.print(chx[5][val]); Serial.print("\t");
        Serial.print(chx[6][val]); Serial.print("\t");
        Serial.print(chx[7][val]); Serial.print("\t");
        Serial.println(chx[8][val]);
        // mi sembra bello confuso
        // comunque qui abbiamo i valori appena stampati
        // ok
        // trasmettiamoli
        // sono int, quindi non possiamo fare write brutale brutale
        // io consiglio sempre di trasmettere in ASCII, perchè è più facile “capire” se ci sono problemi
        // sequenza di trasmissione:
        // un carattere di start
        // un indicatore di canale
        // il primo canale
        // un indicatore di canale
        // il secondo canale…
        // al termine mettiamo un carattere di stop
        RS232.print(START);

for (byte i = 0; i < 9; i++)
        {
            RS232.write(‘A’ + i); // separatore e’ la lettera che identifica il canale A=0, B=1…
            RS232.print(chx[i][val]);
            // stampato
        }

RS232.print(STOP);
    }
}

void decodePPM()
{
    lt    = micros();
    tfail = millis();
    x    = lt - ft;
    ft    = lt;

if (x > 3000)
    {
        ch          = 0;
        chx[0][val] = x;
    }
    else
    {
        ch += 1;
        int indx      = chx[ch][idx];
        chx[ch][total] = chx[ch][total] - chx[ch][indx];
        chx[ch][indx]  = x;
        chx[ch][total] = chx[ch][total] + chx[ch][indx];
        chx[ch][idx]  = chx[ch][idx] + 1;

if (chx[ch][idx] > 9)
        {
            chx[ch][idx] = 0;
        }

chx[ch][val] = chx[ch][total] / 10;
    }
}



vedi se ti ritrovi, tra poco attacca montalbano, casomai domani se ne parla

Buongiorno,

Com’era il commissario? :smiley: :smiley:

Ho guardato bene il codice,
diciamo che mi sono un po’ imbarazzato nel pensare (basta fare così?!)…
Ho quindi fatto qualche modifica…Per togliere cose inutili tipo i serial.print

unsigned long int ft, lt, x, tfail;
int ch, chx[9][13];

const int idx   = 10;
const int total = 11;
const int val   = 12;
#include <SoftwareSerial.h>
#define RX 3
#define TX 4
// i piedini per la softserial

#define START '#' //inizio trasmissione
#define STOP '*' // fine trasmissione

SoftwareSerial RS232(RX, TX);
void setup()
{
    Serial.begin(9600);
    RS232.begin(9600);
    pinMode(2, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(2), decodePPM, FALLING);
}

void loop()
{
    if ((millis() - tfail) > 500)
    {
        Serial.println("Disconnect");
    }
    else
    {
        // io consiglio sempre di trasmettere in ASCII, perchè è più facile "capire" se ci sono problemi
        // sequenza di trasmissione:
        // un carattere di start
        // un indicatore di canale
        // il primo canale
        // un indicatore di canale
        // il secondo canale.....
        // al termine mettiamo un carattere di stop
        RS232.print(START);

        for (byte i = 0; i < 9; i++)
        {
            RS232.write('A' + i); // separatore e' la lettera che identifica il canale A=0, B=1.....
            RS232.print(chx[i][val]);
            // stampato
        }

        RS232.print(STOP);
    }
}

void decodePPM()
{...}
}

Mi viene in mente le seguente domanda ora, mi aspetto sul seriale un codice del genere, esatto?

#A1234 B1111 C1234 D1111 E1234 F1111 G1234 H1111 I1234*

Esatto, senza lo spazio prima del separatore successivo

Però ho un dubbio
La trasmissione seriale è lenta di suo…
Siccome la lettura del ppm è fatta con interrupt, non vorrei che ci fossero problemi di timing…
Ti tocca di provare, non sono in grado di fare ipotesi…

Standardoil:
Però ho un dubbio
La trasmissione seriale è lenta di suo...
Siccome la lettura del ppm è fatta con interrupt, non vorrei che ci fossero problemi di timing.....
Ti tocca di provare, non sono in grado di fare ipotesi...

Fosse invece di aumentare il baud rate a 57600? Magari potrebbe cambiare

Quindi, ora lo step che provo a fare è il seguente, cablare il circuito e mettere in ingresso al modem il mio arduino, in ricezione invece utilizzo putty per verificare la ricezione, può funzionare?

Grazie mille per il momento

La configurazione funziona di certo
Occhio però che la seriale sw non arriva a quelle velocità.