Pages: [1] 2 3   Go Down
Author Topic: RS485 per programmare ATmega  (Read 2457 times)
0 Members and 1 Guest are viewing this topic.
Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve smiley

Supponiamo che io abbia un cavo UTP sulla trentina di metri che mi colleghi un convertitore USB-rs485 ad un max485 sul mio arduino, vorrei usare questa stessa linea per la programmazione dell'ATmega.
Sappiamo che questo standard è un half-duplex, quindi per ricevere devo avere sui pin 2,3 del max uno stato basso e viceversa per inviare..
Ora, il convertitore usb dovrebbe comportarsi così: sto in ascolto->devo inviare qualcosa?allora mi metto in trasmissione->torno di nuovo in ascolto(e  lo fa)
Ma non il max montato sull'arduino. O meglio, non se non glielo dico esplicitamente io da codice.

Oltre ad usare lo standard 422 che implementa due linee separate e sempre differenziali per ogni direzione della trasmissione, c'è un modo per raggirare questo problema?
Come faccio a scrivere sul micro che quando lo programmo, se riceve deve impostare a livello basso un determinato piedino e viceversa quando trasmette?

(Sto dando per scontato che quando programmo un ATmega oltre a mandargli dati devo riceverli anche..)

Spero di essere stato chiaro smiley-grin
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22973
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hai dimenticato che l'Atmega328 in remoto deve essere resettato, altrimenti non può essere avviato il bootloader per ricevere lo sketch dalla seriale e scriverlo in Flash.

Logged


BZ (I)
Online Online
Brattain Member
*****
Karma: 271
Posts: 21879
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Anch io vedo il problema nel reset del Arduino. Il problema del interfaccia per trasmetter i dati é secondario se non risolvi il problema del reset. Ok potresti usare 2 doppini: 1 RX 1 TX e il terzo per il reset.

Ciao Uwe
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22973
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Spedito il segnale di reset non sarebbe un grosso problema modificare il bootloader affinché commuti la linea 485 in ricezione. Linea che poi verrebbe pilotata normalmente dallo sketch una volta che questo riparte.
Logged


Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Momento,momento,moomeeento :p
Perciò che idea avete riguardo il fatto che devo alternare lo stato dei 2 pin del max durante la fase di cariamento?

Edit: modificare il bootloader.. e che ci scrivo? smiley
« Last Edit: March 03, 2013, 01:40:36 am by sciorty » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22973
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Momento,momento,moomeeento :p
Perciò che idea avete riguardo il fatto che devo alternare lo stato dei 2 pin del max durante la fase di cariamento?

Edit: modificare il bootloader.. e che ci scrivo? smiley
Le istruzioni in C  smiley-razz

A parte gli scherzi, che ci vuoi scrivere? Un digitalWrite sul pin a cui hai collegato i 2 pin del Max485 in modo da mettere il chip in ricezione, poi lasci il resto del bootloader inalterato. In questo modo al reset, il bootloader imposta il Max in ricezione e poi riceve lo sketch. Secondo me funziona.
Logged


Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma durante la fase di caricamento l'atmega non invia anche dei dati oltre che riceverli? non so, roba tipo handshake.. anche perchè sulla scheda vedo che si accendono entrambi i led!

Per il reset dovrei farcela: mettiamo che la sezione del cavo utp sia 1mm la resistenza è di 19,5ohm/km, e mettendo proprio per assurdo che il pin reset assorba 1A calcolo una caduta sul cavo di 1V e qualcosa.. se non sto sbagliando..
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22973
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma durante la fase di caricamento l'atmega non invia anche dei dati oltre che riceverli? non so, roba tipo handshake.. anche perchè sulla scheda vedo che si accendono entrambi i led!
Sì, devi analizzare il codice dell'Optiboot e modificarlo in modo che ogni volta che deve ricevere o che deve trasmettere sulla seriale venga settato il Max nel corretto stato.

Quote
Per il reset dovrei farcela: mettiamo che la sezione del cavo utp sia 1mm la resistenza è di 19,5ohm/km, e mettendo proprio per assurdo che il pin reset assorba 1A calcolo una caduta sul cavo di 1V e qualcosa.. se non sto sbagliando..
Qui non mi esprimo  smiley-sweat
Logged


Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ma durante la fase di caricamento l'atmega non invia anche dei dati oltre che riceverli? non so, roba tipo handshake.. anche perchè sulla scheda vedo che si accendono entrambi i led!
Sì, devi analizzare il codice dell'Optiboot e modificarlo in modo che ogni volta che deve ricevere o che deve trasmettere sulla seriale venga settato il Max nel corretto stato.

Non so proprio dove mettere mani, cioè non so neanche dove risiedano questi codici  smiley-sweat

Se i miei calcoli erano giusti avrei potuto usare la rs232 anche se tirata per il collo, mi sarei risparmiato i 20 euro del convertitore usbrs485  smiley-eek smiley-cry
Logged

BZ (I)
Online Online
Brattain Member
*****
Karma: 271
Posts: 21879
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Per il reset dovrei farcela: mettiamo che la sezione del cavo utp sia 1mm la resistenza è di 19,5ohm/km, e mettendo proprio per assurdo che il pin reset assorba 1A calcolo una caduta sul cavo di 1V e qualcosa.. se non sto sbagliando..
per fortuna c'é sul Arduino sulla USB un fusibile da 0,5A.  smiley-twist smiley-twist
Logged

Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Lo sapevo che avrei dovuto sottolinearlo quell' "assurdo" smiley-razz
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22973
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non so proprio dove mettere mani, cioè non so neanche dove risiedano questi codici  smiley-sweat
Sono in /arduino-1.0.3/hardware/arduino/bootloaders/optiboot
Logged


Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

E mo'?  smiley-lol

Posso dedurre sia da cercare in questa zona.. (?):
Code:
/* Forever loop */
  for (;;) {
    /* get character from UART */
    ch = getch();

    if(ch == STK_GET_PARAMETER) {
      unsigned char which = getch();
      verifySpace();
      if (which == 0x82) {
/*
* Send optiboot version as "minor SW version"
*/
putch(OPTIBOOT_MINVER);
      } else if (which == 0x81) {
  putch(OPTIBOOT_MAJVER);
      } else {
/*
* GET PARAMETER returns a generic 0x03 reply for
         * other parameters - enough to keep Avrdude happy
*/
putch(0x03);
      }
    }
    else if(ch == STK_SET_DEVICE) {
      // SET DEVICE is ignored
      getNch(20);
    }
    else if(ch == STK_SET_DEVICE_EXT) {
      // SET DEVICE EXT is ignored
      getNch(5);
    }
    else if(ch == STK_LOAD_ADDRESS) {
      // LOAD ADDRESS
      uint16_t newAddress;
      newAddress = getch();
      newAddress = (newAddress & 0xff) | (getch() << 8);
#ifdef RAMPZ
      // Transfer top bit to RAMPZ
      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
#endif
      newAddress += newAddress; // Convert from word address to byte address
      address = newAddress;
      verifySpace();
    }
    else if(ch == STK_UNIVERSAL) {
      // UNIVERSAL command is ignored
      getNch(4);
      putch(0x00);
    }
    /* Write memory, length is big endian and is in bytes */
    else if(ch == STK_PROG_PAGE) {
      // PROGRAM PAGE - we support flash programming only, not EEPROM
      uint8_t *bufPtr;
      uint16_t addrPtr;

      getch(); /* getlen() */
      length = getch();
      getch();

      // If we are in RWW section, immediately start page erase
      if (address < NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);

      // While that is going on, read in page contents
      bufPtr = buff;
      do *bufPtr++ = getch();
      while (--length);

      // If we are in NRWW section, page erase has to be delayed until now.
      // Todo: Take RAMPZ into account
      if (address >= NRWWSTART) __boot_page_erase_short((uint16_t)(void*)address);

      // Read command terminator, start reply
      verifySpace();

      // If only a partial page is to be programmed, the erase might not be complete.
      // So check that here
      boot_spm_busy_wait();

#ifdef VIRTUAL_BOOT_PARTITION
      if ((uint16_t)(void*)address == 0) {
        // This is the reset vector page. We need to live-patch the code so the
        // bootloader runs.
        //
        // Move RESET vector to WDT vector
        uint16_t vect = buff[0] | (buff[1]<<8);
        rstVect = vect;
        wdtVect = buff[8] | (buff[9]<<8);
        vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
        buff[8] = vect & 0xff;
        buff[9] = vect >> 8;

        // Add jump to bootloader at RESET vector
        buff[0] = 0x7f;
        buff[1] = 0xce; // rjmp 0x1d00 instruction
      }
#endif

      // Copy buffer into programming buffer
      bufPtr = buff;
      addrPtr = (uint16_t)(void*)address;
      ch = SPM_PAGESIZE / 2;
      do {
        uint16_t a;
        a = *bufPtr++;
        a |= (*bufPtr++) << 8;
        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
        addrPtr += 2;
      } while (--ch);

      // Write from programming buffer
      __boot_page_write_short((uint16_t)(void*)address);
      boot_spm_busy_wait();

#if defined(RWWSRE)
      // Reenable read access to flash
      boot_rww_enable();
#endif

    }
    /* Read memory block mode, length is big endian.  */
    else if(ch == STK_READ_PAGE) {
      // READ PAGE - we only read flash
      getch(); /* getlen() */
      length = getch();
      getch();

      verifySpace();
#ifdef VIRTUAL_BOOT_PARTITION
      do {
        // Undo vector patch in bottom page so verify passes
        if (address == 0)       ch=rstVect & 0xff;
        else if (address == 1)  ch=rstVect >> 8;
        else if (address == 8)  ch=wdtVect & 0xff;
        else if (address == 9) ch=wdtVect >> 8;
        else ch = pgm_read_byte_near(address);
        address++;
        putch(ch);
      } while (--length);
#else
#ifdef __AVR_ATmega1280__
//      do putch(pgm_read_byte_near(address++));
//      while (--length);
      do {
        uint8_t result;
        __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
        putch(result);
        address++;
      }
      while (--length);
#else
      do putch(pgm_read_byte_near(address++));
      while (--length);
#endif
#endif
    }

    /* Get device signature bytes  */
    else if(ch == STK_READ_SIGN) {
      // READ SIGN - return what Avrdude wants to hear
      verifySpace();
      putch(SIGNATURE_0);
      putch(SIGNATURE_1);
      putch(SIGNATURE_2);
    }
    else if (ch == 'Q') {
      // Adaboot no-wait mod
      watchdogConfig(WATCHDOG_16MS);
      verifySpace();
    }
    else {
      // This covers the response to commands like STK_ENTER_PROGMODE
      verifySpace();
    }
    putch(STK_OK);
  }
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 333
Posts: 22973
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Intorno alla riga 292, metti l'attivazione del chip in ricezione.

Code:
  // Adaboot no-wait mod
  ch = MCUSR;
  MCUSR = 0;
  if (!(ch & _BV(EXTRF))) appStart();
***************** QUI  ************
#if LED_START_FLASHES > 0
Questo punto è buono perché è subito dopo la disattivazione di un eventuale watchdog e subito prima del proseguo del bootloader, dove viene qualche riga più sotto aperta la seriale.

Usa però la manipolazione diretta delle porte logiche, perché altrimenti digitalWrite non funziona (non hai il core Arduino caricato)..
A questo punto, la cosa diventa più maia....
Alla riga 503 c'è la funzinoe putch, che spedisce un byte sulla seriale. Qui dovresti mettere la funzione per attivare il Max in trasmissione.
Alla riga 533 c'è la funzione getch, che riceve un byte. Qui invece devi mettere la funzione per attivare il Max in ricezione.

Fatto questo, compili, flashi e... preghi  smiley-wink
Logged


Capo d'Orlando
Offline Offline
God Member
*****
Karma: 2
Posts: 725
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Usa però la manipolazione diretta delle porte logiche

Leo, ma per chi mi hai preso? :p vedo se riesco in qualche maniera a farmi aiutare a scuola smiley
Logged

Pages: [1] 2 3   Go Up
Jump to: