[RISOLTO] Errore nei primi 8 byte utilizzando pin RX e TX come seriale

Ciao a tutti.

Ho un problema utilizzando la seriale di arduino tramite i pin RX e TX (0 e 1) invece che tramite usb.

Innanzitutto allego il codice che sto utilizzando (un semplice echo del carattere che spedisco dal serial monitor).

char incomingByte = 0;    // for incoming serial data

void setup() {
    Serial.begin(9600);    // opens serial port, sets data rate to 9600 bps
}

void loop() {
  // send data only when you receive data:
  if (Serial.available() > 0) {
  
    // read the incoming byte:
    incomingByte = Serial.read();
  
    // say what you got:
    Serial.print((char)incomingByte);
  }
  
}

Sto utilizzando un adattatore usb/seriale che sono sicuro che funziona (lo utilizzo al lavoro quotidianamente). Collego come segue:

  • il pin 3 (TX) dell'adattatore usb/seriale al pin 0 (RX) di arduino;
  • il pin 2 (RX) dell'adattatore usb/seriale al pin 1 (TX) di arduino;
  • il pin 5 (GND) dell'adattatore usb/seriale alla massa di arduino;

Carico lo sketch e mi collego con la serial monitor: se provo a scrivere singoli caratteri, questi vengono ricevuti e rispediti (se mando un carattere mi viene risposto un carattere, se ne mando due mi viene risposto due caratteri e così via). Il problema è che non sono corretti: è come se ci fosse il baudrate errato.

Riporto due esempi per far capire meglio:

  • spedisco '1' -> ricevo 'L';
  • spedisco '1234 -> ricevo 'L&¢>";

Ho notato però che spedisco più di 8 caratteri insieme, a partire dal nono carattere comincia a rispondere correttamente. Per esempio:

  • spedisco '1234567890' -> ricevo 'L&"*2:90'
  • spedisco '12345678ora comincia a rispondere in modo corretto' -> ricevo 'L&¢ª²:ora comincia a rispondere in modo corretto'

Ho a disposizione anche un programmatore avr-dragon e un atmega328p vergine senza bootloader che sto comincia ad utilizzare con tutta la toolchain di avr (per fare anche debug hardware con debugwire). Mi sono fatto il mio driver per la seriale ed ho lo stesso identico problema: ho provato a controllare com'è fatto il driver della seriale di arduino nei sorgenti ed è fatto esattamente come il mio.

Riporto anche il mio driver seriale che utilizzo con l'atmega328p e la toolchain avr se può tornare utile.

#include <avr/io.h>
#include <avr/interrupt.h>

#include <string.h>

#include "ser.h"

#define UBRR ((F_CPU / (SER_BAUD_RATE * 16UL)) - 1)

static char ser_rcved_byte; /* Received byte via serial comm. */

/** 
 * Interrupt service routine on usart rx.
 * 
 * @param USART_RX_vect usart rx vector.
 * 
 * @return 
 *
 * @warning global interrupt (function sei()) must be already called.
 */
ISR(USART_RX_vect)
{
  while ((UCSR0A & _BV(RXC0)) == 0)
    ;

  ser_rcved_byte = UDR0;
  
  while ((UCSR0A & _BV(UDRE0)) == 0)
    ;
  
  UDR0 = ser_rcved_byte;
}

/** 
 * Initializes serial module.
 * 
 */ 
void
ser_init(void)
{
  uint16_t ubrr;
  
  ubrr = ((F_CPU / (SER_BAUD_RATE * 16UL)) - 1);
  
  /* Set baud rate. */
  UBRR0H = ubrr >> 8;
  UBRR0L = ubrr;
  
  UCSR0B |= _BV(RXEN0) | _BV(TXEN0); /* Enable receiver and transmitter. */
  
  UCSR0B |= _BV(RXCIE0); /* Enable reciever interrupt. */
  
  if(SER_DATA_BITS == 8 && SER_STOP_BITS == 1)
    {
      UCSR0C |= _BV(UCSZ01) | _BV(UCSZ00); /* Set frame (8 data bits - 1 stop bit). */
    }
}

Ho provato ad alimentare arduino sia con l'usb del portatile attaccato all'adattatore usb/seriale che con l'usb di un altro portatile: stesso problema.

Ho provato anche con baudrate diversi: identico comportamento.

Sbaglio io o mi sfugge qualcosa?

Grazie mille.

Buona serata a tutti.

Non ho esaminato nulla, ma mi è saltato subito all'occhio la prima riga

int incomingByte = 0;    // for incoming serial data

... stai ricevendo dei singoli caratteri quindi :

char incomingByte = 0;    // for incoming serial data

... se non altro ... risparmi un byte :wink:

Poi, di sicuro, c'è anche qualche altro problema ...

Guglielmo

Grazie per la correzione: non me ne ero accorto :slight_smile:

In ogni caso, non cambia nulla purtroppo.

Prova a sostituire print() con write() così sei sicuro di inviare un byte. Il tuo codice comunque funziona (l'ho provato con la connessione seriale classica cioè quella tramite usb di serie) quindi credo che sia un errore di comunicazione tra i due dispositivi. Che adattatore seriale è?

yoshi93:
Prova a sostituire print() con write() così sei sicuro di inviare un byte. Il tuo codice comunque funziona (l'ho provato con la connessione seriale classica cioè quella tramite usb di serie) quindi credo che sia un errore di comunicazione tra i due dispositivi. Che adattatore seriale è?

Ciao,

coin la connessione seriale via usb non ho nessun problema: funziona tutto perfettamente. E' utilizzando i pin 0 e 1 (RX e TX) che mi fa casino sui primi 8 byte.

Ho provato comunque utilizzando la write ma il problema rimane.

Serial.write(incomingByte);

L'adattatore usb/seriale che ho monta un chip prolific. Per la precisione (ho un mac):

                USB-Serial Controller D:

                  Product ID: 0x2303
                  Vendor ID: 0x067b  (Prolific Technology, Inc.)
                  Version: 4.00
                  Speed: Up to 12 Mb/sec
                  Manufacturer: Prolific Technology Inc. 
                  Location ID: 0x1a124000 / 6
                  Current Available (mA): 500
                  Current Required (mA): 100

Per scrupolo ho provato anche col computer di lavoro (con ubuntu), su cui sono sicuro che il medesimo usb/seriale e i relativi driver funzionano in quanto lo uso quotidianamente a lavoro per debug, ma il risultato ahimè non cambia.

Potrei pensare che è l'arduino rotto, ma con un atmega328p vergine (senza bootloader) con il driver per la seriale riportato nel primo post ottengo lo stesso risultato.

Avevo letto che quando si utilizzano i pin 0 e 1 per comunicare via seriale non bisogna alimentare l'arduino con l'usb perché altrimenti fa casino con l'ftdi montato sulla scheda: il problema è che con l'atmega328p (montato su breadboard col minimo indispensabile e che dell'ftdi non ne sa neanche l'esistenza) ottengo gli stessi risultati. Quindi con certezza posso dire che i chip sono funzionanti.

Penso che mi sfugga qualcosa nei collegamenti elettrici o nelle alimentazioni, ma non so cosa. Certo che se dopo il byte n°8 funziona correttamente, penso ci sia qualcosa di errato nei driver seriale di arduino.

Possibile? Pensandoci meglio no, perché utilizzando la classica usb ricevo tutto senza problemi e i driver sono gli stessi.

EDIT: spulciando un po' su google, ho trovato questo link che utilizza i pin 2 e 3 di un atmega168 (corrispondenti ai pin 0 e 1 se si pensa ad un arduino 2009) per la seriale ad un connettore db9.

http://imagearts.ryerson.ca/sdaniels/physcomp/tutorials/arduino_serial/ard_serial.html

Ho notato che utilizza questo integrato (penso che sia un inverter per i livelli):

http://www.parl.clemson.edu/~wjones/371/chips/7404.pdf

La mia conoscenza hardware ahimè è abbastanza limitata: sposto la sezione in hardware? Che sia questo il problema?

Non vorrei cominciare a dire stronzate :slight_smile: Stasera stacco la testa: domani faccio mente locale e vedo se ne cavo qualcosa.

Se qualcuno nel frattempo mi sa dare qualche dritta ne sarei grato :slight_smile:

Buona serata.

Se tutto funziona normalmente dopo l'invio di 8 byte potresti inviarli sempre quando devi stabilire una connessione. Non è la soluzione più elegante però potrebbe funzionare. Vedi comunque questa discussione se ti può tornare utile: http://arduino.cc/forum/index.php?topic=143781.0

yoshi93:
Se tutto funziona normalmente dopo l'invio di 8 byte potresti inviarli sempre quando devi stabilire una connessione. Non è la soluzione più elegante però potrebbe funzionare. Vedi comunque questa discussione se ti può tornare utile: Arduino Forum

Ho provato anche a impostare il pin 0 in output come scritto nel topic ma nulla.

Comunque la soluzione che hai proposto non è che non sia elegante: non è proprio accettabile! Anche perché comunque non è che mando 8 byte e dai in poi funziona: per farlo funzionare, ogni volta che voglio spedire qualcosa devo mandare 8 byte e dal 9° in poi mandare quello che voglio scrivere.

Ho provato a rifare mente locale ma non ne esco fuori: avessi un oscilloscopio capirai qualcosa in più.

Se è così allora è veramente inaccettabile come soluzione. Hai provato a far comunicare magari 2 arduino oppure provare con un altro convertitore seriale?

yoshi93:
Se è così allora è veramente inaccettabile come soluzione. Hai provato a far comunicare magari 2 arduino oppure provare con un altro convertitore seriale?

Purtroppo al momento non ho due arduino con cui provare. Ho provato anche con un altro convertitore seriale ma ho lo stesso problema (c'è da dire che usa lo stesso chip prolific pl2303).

Non so più dove sbattere la testa: qualcuno potrebbe fare una prova col proprio arduino ed un usb/serial sui pin RX TX e vedere se ha lo stesso problema?

Come mi è stato fatto notare oggi da un collega, senza un Maxim 3232 (http://datasheets.maximintegrated.com/en/ds/MAX3222-MAX3241.pdf) tra adattatore usb/seriale e pin RX TX di arduino non vado molto lontano :slight_smile:

Problem solved 8)