[RISOLTO] Collegamento Arduino/Attiny84 via RS485 e Modbus

Buongiorno a tutti,
dopo aver raccolto informazioni per diverso tempo e dopo che mi sono arrivati gli Attiny84 e i MAX485 oggi mi sono messo a fare il mio primo esperimento per far comunicare Arduino con un Attiny84 e nulla… qualcosa non funziona :frowning:

In allegato riporto il disegno con le connessioni che ho fatto (nel disegno c’è un attiny85 anzichè un attiny84, ma è la prima volta che utilizzo Fritzing e non so ancora come aggiungere componenti nuovi), e le due resistenze sono da 120 Ohm.

Qualcuno sa se ho dimenticato o sbagliato qualcosa sul lato elettronico?

Per quanto riguarda il software nei prossimi giorni provo a studiare meglio gli esempi da cui sono partito con SimpleModbus e nel caso non riesca a venirne a capo riporterò il codice usato.

Grazie a tutti per l’aiuto :wink:

E' possibile vedere gli sketch dei 2 chip, Tiny84 e Arduino?

leo72: E' possibile vedere gli sketch dei 2 chip, Tiny84 e Arduino?

Appena riesco li posto ;) , magari prima faccio qualche altra prova sperando di risolvere senza disturbarvi.

Nel mentre qualcuno mi sa dire i collegamenti che ho allegato sono corretti? Pi√Ļ che altro vorrei evitare di bruciare tutto per errore :roll_eyes:

Piccolo aggiornamento che mi lascia pensare ad un problema lato software, ovvero cosa succede quando nel codice scrivo ‚ÄúdigitalWrite(0, HIGH)‚ÄĚ?

Cercando in internet avevo trovato diverse immagini pi√Ļ o meno concordanti, evidentemente non sono stato in grado di leggerle nella maniera corretta perch√® il PIN0 non era quello che immaginavo.

Comunque sia armato di led ho provato tutti i pin uno a uno con il mio Attiny84A, se può essere utile allego l’immagine della piedinatura con i relativi pin di arduino (indicati tra parentesi).

Nei prossimi giorni farò nuovamente prove per la comunicazione su RS485

pin_arduino_attiny84.jpg

Stai usando il core Tiny, immagino.
Il pin digitale 0 è PB0, sul core Tiny.
La piedinatura usata dal core è quella della tua immagine.

leo72: Stai usando il core Tiny, immagino. Il pin digitale 0 è PB0, sul core Tiny. La piedinatura usata dal core è quella della tua immagine.

Per il core e la configurazione dell'IDE (uso la 1.5.8 ) mi sono attenuto alla tua guida aggiornata qualche giorno fa (tra l'altro complimenti, chiara e completa mi ha permesso di configurare l'IDE in pochi minuti, in un unico archivio c'è tutto quello che serve ;) ).

A proposito, solo una cosa non mi è chiara, in fase di compilazione ho settato l'IDE per Attiny84 con frequenza a 8Mhz e cristallo interno anche perchè altrimenti la SoftwareSerial non funzionerebbe, infine uso un Arduino UNO R3 come ISP.

Gli script vengono caricati e sembrano andare (almeno provando quelli semplici per accendere e spegnere dei led), l'unica stranezza è che il comando "delay(1000)" dura 8 secondi, impostando dall'IDE 1Mhz le tempistiche tornano corrette, devo fare qualche altra configurazione?

Devi settare i fuse per impostare il clock interno a 8MHz, altrimenti ti lavora con la configurazione originale a 1MHz; dovrebbe essere sufficiente fare un caricamento di bootloader per ottenere questo risultato, poi riprogrammi il micro via ISP e ti funzionerà tutto correttamente. In alternativa puoi lavorare con AVRDUDE via riga di comando o mediante la GUI AVRDUDESS, molto semplice da usare.

Sì, se hai il delay di 8 secondi il chip sta andando a 1 MHz e la seriale software a quella frequenza non funziona. Devi impostare il chip a 8 MHz, come ti ha detto Michele.

:sweat_smile: come al solito mi ero perso qualcosa, in pratica mi basterebbe usare la funzionalit√† sull‚ÄôIDE ‚ÄúStrumenti->Scrivi il bootloader‚ÄĚ ?

Giusto per chiarezza riporto tutti i passaggi che faccio attualmente a cui aggiungo quello del bootloader…

  • Collego Arduino UNO R3 all‚ÄôIDE e carico il programma ArduinoISP gi√† presente negli esempi
  • Collego Arduino al mio AtTiny84A seguendo questo schema
  • Imposto l‚ÄôIDE per l‚ÄôAtTiny84 a 8Mhz con cristallo interno e Arduino come ISP
  • Utilizzo la funzionalit√† ‚ÄúStrumenti->Scrivi il bootloader‚ÄĚ (passaggio da effettuare soltanto quando cambio la frequenza)
  • Carico il mio sketch sull‚ÄôAtTiny84

E’ tutto corretto?

YES, non ho controllato i collegamenti ISP ma visto che sei già riuscito a caricare lo sketch di sicuro sono esatti ;) Naturalmente la board virtuale del tiny84 dovrà avere la riga con il path per il bootloader, che potrà anche essere un "empty".

[quote author=Michele Menniti date=1415877095 link=msg=1959928] Naturalmente la board virtuale del tiny84 dovrà avere la riga con il path per il bootloader, che potrà anche essere un "empty". [/quote]

Per un istante dopo aver letto la tua risposta la mia faccia è stata questa --> :fearful:

Comunque sono andato nella cartella "hardware\tiny\avr\bootloaders\empty" dove tra i vari file c'è anche "empty84at8.hex" che è quello che dovrebbe servire a me, e nel file "board.txt" tra le configurazioni dell'Attiny84 c'è "tinyx4.menu.cpu.attiny84at8.bootloader.file=empty84at8.hex" quindi dovrebbe essere tutto corretto.

Sì, è la path giusta.

Che fuse sono riportati nella board? Usi quella standard del core tiny?

PaoloP: Che fuse sono riportati nella board? Usi quella standard del core tiny?

Questa è la configurazione all'interno del file boards.txt, ma credo proprio che sia corretta.

tinyx4.menu.cpu.attiny84at8=ATtiny84 @ 8 MHz  (internal oscillator; BOD disabled)

tinyx4.menu.cpu.attiny84at8.upload.tool=arduino:arduinoisp
tinyx4.menu.cpu.attiny84at8.upload.maximum_size=8192
tinyx4.menu.cpu.attiny84at8.upload.maximum_data_size=512

# Default clock (slowly rising power; long delay to clock; 8 MHz internal)
# Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 64 ms; [CKSEL=0010 SUT=10]; default value
# Brown-out detection disabled; [BODLEVEL=111]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]

tinyx4.menu.cpu.attiny84at8.bootloader.low_fuses=0xE2
tinyx4.menu.cpu.attiny84at8.bootloader.high_fuses=0xD7
tinyx4.menu.cpu.attiny84at8.bootloader.extended_fuses=0xFF
tinyx4.menu.cpu.attiny84at8.bootloader.path=empty
tinyx4.menu.cpu.attiny84at8.bootloader.file=empty84at8.hex

tinyx4.menu.cpu.attiny84at8.build.mcu=attiny84
tinyx4.menu.cpu.attiny84at8.build.f_cpu=8000000L
tinyx4.menu.cpu.attiny84at8.build.core=tiny

Ora che mi hanno detto che devo procedere alla riscrittura del bootloader non mi resta che provare, poi passerò alle prove con la seriale/softwareserial concludendo poi con Modbus.

Se tutto va come deve andare aggiungerò alla discussione i codici funzionanti 8), in caso contrario... bhè ci sentiremo prima :sweat_smile: ...

Se ti possono essere d'aiuto, sul mio sito ho un paio di guide per l'uso dei Tiny (per IDE 1.0.x e 1.5.x). Link in calce alla mia firma.

I fuse sono corretti. Adesso devi leggere quelli del micro con AVRdude per vedere se sono gli stessi. Meglio installare AVRdudess. (http://blog.zakkemble.co.uk/avrdudess-a-gui-for-avrdude/) Una volta lanciato selezioni Arduino, la porta Com e premi "detect" e poi "fuse read".

Mini aggiornamento (purtroppo questa sera ho avuto a disposizione solo pochi minuti), dopo aver usato la funzione "Scrivi bootloader" magicamente il mio Attiny84 ha iniziato ad andare effettivamente a 8Mhz :grinning: Grazie a tutti per la dritta, nei prossimi giorni procederò con il resto :sunglasses:

Rieccomi con un aggiornamento, i collegamenti funzionano tutti (in allegato i collegamenti che ho fatto) e finalmente il mio Arduino comunica con l’Attiny84 anche se non ancora con Modbus.

Per fare dei test ho usato il codice presente qui modificandolo leggermente.

Codice del Master (Arduino)

#include "RS485_protocol.h"
#include <SoftwareSerial.h>

const byte ENABLE_PIN = 4;
const byte LED_PIN = 13;

SoftwareSerial rs485 (2, 3);  // receive pin, transmit pin

// callback routines
  
void fWrite (const byte what)
  {
  rs485.write (what);  
  }
  
int fAvailable ()
  {
  return rs485.available ();  
  }

int fRead ()
  {
  return rs485.read ();  
  }

void setup()
{
  rs485.begin (28800);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  pinMode (LED_PIN, OUTPUT);  // built-in LED
  
  Serial.begin(9600);//for debug
}  // end of setup

byte brightness = 0;    // how bright the LED is
byte fadeAmount = 10;    // how many points to fade the LED by


void loop()
{

   // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade: 
  if (brightness == 0 || brightness == 50) {
    fadeAmount = -fadeAmount ; 
  }     
 
  // assemble message
  byte msg [] = { 
     1,    // device 1
     2,    // set fade
     brightness // to what level
  };
  
  Serial.print("SEND: ");
  Serial.print(msg[0]);
  Serial.print("-");
  Serial.print(msg[1]);
  Serial.print("-");
  Serial.println(msg[2]);

  // send to slave  
  digitalWrite (ENABLE_PIN, HIGH);  // enable sending
  sendMsg (fWrite, msg, sizeof msg);
  digitalWrite (ENABLE_PIN, LOW);  // disable sending

  // receive response  
  byte buf [10];
  byte received = recvMsg (fAvailable, fRead, buf, sizeof buf);  
  Serial.print("RECIVE ");
  Serial.print(buf[0]);
  Serial.print("-");
  Serial.println(buf[1]);
  digitalWrite (LED_PIN, received == 0);  // turn on LED if error
}  // end of loop

Codice dello Slave (Attiny84)

#include <SoftwareSerial.h>
#include "RS485_protocol.h"

SoftwareSerial rs485 (2, 3);  // receive pin, transmit pin
const byte ENABLE_PIN = 4;
const byte LED_PIN = 5;

void fWrite (const byte what)
  {
  rs485.write (what);  
  }
  
int fAvailable ()
  {
  return rs485.available ();  
  }

int fRead ()
  {
  return rs485.read ();  
  }
  
void setup()
{
  rs485.begin (28800);
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
}

void loop()
{
  byte buf [20];
  
  byte received = recvMsg (fAvailable, fRead, buf, sizeof (buf) - 1);
  
  if (received)
    {
    if (buf [0] != 1)
      return;  // not my device
      
    if (buf [1] != 2)
      return;  // unknown command
    
    byte msg [] = {
       0,  // device 0 (master)
       3,  // turn light on command received
    };
    
    delay (1);  // give the master a moment to prepare to receive
    digitalWrite (ENABLE_PIN, HIGH);  // enable sending
    sendMsg (fWrite, msg, sizeof msg);
    digitalWrite (ENABLE_PIN, LOW);  // disable sending
    
    analogWrite (LED_PIN, buf [2]);  // set fade level
   }  // end if something received
   
}  // end of loop

I messaggi inviati dall’Arduino vengono correttamente letti dall’Attiny che cambia l’intensità luminosa del led… Purtroppo le risposte arrivano sbagliate, sono sempre valori fissi, ma non quelli che mi aspetto ::slight_smile:
Continuerò a fare delle prove e ad andare avanti, appena ho novità vi aggiorno.

Giusto per chiudere tutto il giro, sono riuscito a risolvere con i problemi di comunicazione tra AtTiny84 e Arduino, i collegamenti e il codice sono gli stessi che ho scritto nel post precedente.

Le uniche modifiche che ho apportato sono:

L'inizializzazione della software serial a 9600 "rs485.begin (9600);", avevo infatti trovato questa pagina, non so se ho frainteso ma mi pare una risorsa utile per scegliere quale bps usare in base alle frequenza del clock del microcontrollore, nel mio caso 16Mhz per aduino e 8Mhz per l'attiny e 9600 sembra un buon valore per entrambi.

L'altra modifica è stata quella di modificare aggiungendo un "delayMicroseconds(50)" nel metodo "recvMsg" subito dopo l'istruzione "byte inByte = fRead ();", quest'ultima modifica non mi è molto chiara e l'ho fatta perchè guardando altre librerie (es. simplemodbus) tra un carattere e l'altro venivano inseriti dei piccoli delay. In ogni caso senza questa piccola pausa il master non riusciva a leggere le risposte quindi al momento l'ho presa per buona.

Per quanto riguarda il passaggio successivo ho deciso di ripiegare su una soluzione custom per quanto riguarda la formattazione del messaggio e la sua gestione, mantenendo tuttavia le logiche di invio/ricezione presenti nelle librerie SimpleModbus.

Grazie a tutti per il prezioso aiuto che mi avete fornito ;)

Ciao

shake84: Giusto per chiudere tutto il giro, sono riuscito a risolvere con i problemi di comunicazione tra AtTiny84 e Arduino, i collegamenti e il codice sono gli stessi che ho scritto nel post precedente.

Le uniche modifiche che ho apportato sono:

L'inizializzazione della software serial a 9600 "rs485.begin (9600);", avevo infatti trovato questa pagina, non so se ho frainteso ma mi pare una risorsa utile per scegliere quale bps usare in base alle frequenza del clock del microcontrollore, nel mio caso 16Mhz per aduino e 8Mhz per l'attiny e 9600 sembra un buon valore per entrambi.

L'altra modifica è stata quella di modificare aggiungendo un "delayMicroseconds(50)" nel metodo "recvMsg" subito dopo l'istruzione "byte inByte = fRead ();", quest'ultima modifica non mi è molto chiara e l'ho fatta perchè guardando altre librerie (es. simplemodbus) tra un carattere e l'altro venivano inseriti dei piccoli delay. In ogni caso senza questa piccola pausa il master non riusciva a leggere le risposte quindi al momento l'ho presa per buona.

Per quanto riguarda il passaggio successivo ho deciso di ripiegare su una soluzione custom per quanto riguarda la formattazione del messaggio e la sua gestione, mantenendo tuttavia le logiche di invio/ricezione presenti nelle librerie SimpleModbus.

Grazie a tutti per il prezioso aiuto che mi avete fornito ;)

shake84: Giusto per chiudere tutto il giro, sono riuscito a risolvere con i problemi di comunicazione tra AtTiny84 e Arduino, i collegamenti e il codice sono gli stessi che ho scritto nel post precedente.

Le uniche modifiche che ho apportato sono:

L'inizializzazione della software serial a 9600 "rs485.begin (9600);", avevo infatti trovato questa pagina, non so se ho frainteso ma mi pare una risorsa utile per scegliere quale bps usare in base alle frequenza del clock del microcontrollore, nel mio caso 16Mhz per aduino e 8Mhz per l'attiny e 9600 sembra un buon valore per entrambi.

L'altra modifica è stata quella di modificare aggiungendo un "delayMicroseconds(50)" nel metodo "recvMsg" subito dopo l'istruzione "byte inByte = fRead ();", quest'ultima modifica non mi è molto chiara e l'ho fatta perchè guardando altre librerie (es. simplemodbus) tra un carattere e l'altro venivano inseriti dei piccoli delay. In ogni caso senza questa piccola pausa il master non riusciva a leggere le risposte quindi al momento l'ho presa per buona.

Per quanto riguarda il passaggio successivo ho deciso di ripiegare su una soluzione custom per quanto riguarda la formattazione del messaggio e la sua gestione, mantenendo tuttavia le logiche di invio/ricezione presenti nelle librerie SimpleModbus.

Grazie a tutti per il prezioso aiuto che mi avete fornito ;)

Ciao, Vorrei fare un qualcosa di molto simile con un attiny85. Potresti cortesemente postarmi le versioni definitive del master(Arduino) e Slave(attiny84) con lo schema utilizzato?