Blog Detail

CAN-ISO: Configurazione del codice e test

08 Feb 19
admin
,
No Comments

In questa sezione vedremo come configurare il modulo RubinoLAB CAN-ISO su Arduino e come testarlo.

Per l’acquisto di CAN-ISO: LINK

Il protocollo implementato utilizza una comunicazione standard ASCII. Ciò rende il sistema compatibile con qualsiasi programma (Python, LabVIEW, MATLAB etc), semplice da adattare al proprio progetto.

Il primo passo da fare è installare la libreria MCP_CAN (se non l’avete già installata), nell’editor Arduino. Qui trovate il link della libreria:

https://github.com/coryjfowler/MCP_CAN_lib

Create un progetto con il codice esempio qui riportato o in alternativa scaricate il progetto allegato e scompattatelo nella vostra cartella di lavoro.

CANINO_v2 CANINO_V2.zip

Compilate e caricatelo nel modulo Arduino.

//revisione 2 del 30/03/2018, con Arduino 1.8.5
/*
  CAN BUS + ARDUINO --> CANINO interface :)
  USB <--> CAN BUS interface
  Author: Luigi Rubino

  Adesso accetta 3 byte di indirizzo

  STRING EXAMPLE:
  @00A0102030405060708\n
*/

#include "mcp_can.h"
#include <SPI.h>

#define CAN0_INT 2                              // Set INT to pin 2
MCP_CAN CAN0(10);                               // Set CS to pin 10


// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
// Can_Bus_shield-ISO-v1 is default D10
//const int SPI_CS_PIN = 10;
//MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin

unsigned char buf[8];
unsigned char canId;
long unsigned int rxId;


#define LEN_STRING 10

unsigned char ReceivedString[LEN_STRING];  //stringa ricezione carattere da USB

int inByte = 0;         // incoming serial byte

//global var
int  digValue, sign=1;
char rxpos, rxpos2;          //per il parser seriale
int address;                //comando da eseguire
int DT;


void setup() {
  // start serial port at 115200 bps:
  Serial.begin(115200); //provare velocità 115200
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
 
  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK)
    Serial.println("MCP2515 Initialized Successfully!");
  else
    Serial.println("Error Initializing MCP2515...");
  
  CAN0.setMode(MCP_NORMAL);                     // Set operation mode to normal so the MCP2515 sends acks to received data.

  pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
  
  Serial.println("CANINO READY...");
}

void loop() {

  unsigned char len = 0;
  
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    //Serial.write(inByte);
    // delay 10ms to let the ADC recover:
    //delay(10);
    
 /* Get the character received from the USART */
  if (inByte=='@')
   {
     rxpos     = 1;
     digValue  = 0;
   }
  else
  {
    
//    Serial.print("-->");
//    Serial.print((int) rxpos);
//    Serial.println();
    
  switch(rxpos)
  {
   case 1:
      address   = hex2int(inByte);
      rxpos    += 1;
      
      break;

   case 2:
      address   <<=4; 
      address += hex2int(inByte);     
      rxpos    += 1;

      break;
      
   case 3:
      address   <<=4; 
      address += hex2int(inByte);    
      rxpos    += 1;
      rxpos2   =  0; 

      break;
                  
   case 4:   //byte 1
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 5:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;

   case 6:   //byte 2
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 7:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;
 
   case 8:   //byte 3
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 9:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;

   case 10:   //byte 4
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 11:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;
      
   case 12:   //byte 5
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 13:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;

   case 14:   //byte 6
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 15:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;

   case 16:   //byte 7
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 17:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;

   case 18:   //byte 8
      DT = hex2int(inByte);
      rxpos    += 1;
      break;
   case 19:
      DT   <<=4; 
      DT += hex2int(inByte);
      ReceivedString[rxpos2] = DT;
      rxpos    += 1;
      rxpos2   += 1;
      break;
                  
   case 20: //eseguo il comando
        CAN0.sendMsgBuf(address, 0, 8, ReceivedString);
        //byte sndStat = CAN0.sendMsgBuf(0x100, 0, 8, data);
    //delay(100);          // send data per 100ms
      rxpos    = 0;

//da rinuovere
//      Serial.print(address, HEX);
//      for (int kk=0;kk<=7; kk++)
//      {
//        Serial.print(" ");
//        Serial.print(ReceivedString[kk], HEX);
//        
//        }
//        Serial.println();
    break;
    default: 
        rxpos    = 0;
        break;
  }
  }    //fine gestione acquisizione 
  }  //fine gestione seriale

  // --------------------------------------------------
  //gestione CAN BUS
  if(!digitalRead(CAN0_INT))                         // If CAN0_INT pin is low, read receive buffer
  {
    CAN0.readMsgBuf(&rxId, &len, buf);      // Read data: len = data length, buf = data byte(s)

    canId = (unsigned char) rxId;
//    canId = CAN0.getCanId();       // indirizzo risposta
        
 //       Serial.println("-----------------------------");
 //       Serial.print("Get data from ID: ");
        Serial.print("@");
        Serial.print(canId, HEX);

        for(int i = 0; i<len; i++)    // print the data
        {
            if (buf[i]<=15)  {  Serial.print('0');}
            Serial.print(buf[i], HEX);
        }
        Serial.println();
    }
 
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}

int hex2int (char c)
{
  if (c >= '0' && c <= '9')
  {
      return (int) (c-'0');
  }
  else
  {
      return (int) ((c - 'A')+10);
  }
}
CANINO library

Adesso siamo pronti per iniziare!

Test del codice (Trasmissione)

Una tipica connessione CAN-Bus nel campo dell’automazione industriale è quella mostrata in figura, dove c’è un master e vari multi slave. Nel master/slave ogni dispositivo o processo (chiamato master) controlla uno o più dispositivi o processi (chiamati slaves). Una volta che la connessione master/slave si è stabilita, la direzione del controllo è sempre dal master allo slave(s).

Per il test del codice è necessario creare una micro-rete CAN-BUS, ad esempio utilizzando due interfacce CAN-BUS Arduino. Per l’esempio qui riportato abbiamo utilizzato una interfacca CAN-BUS Arduino connessa a una interfaccia commerciale.

NB. L’interfaccia è configurata per una velocità di comunicazione CAN di 500kbps. Cambiate questo valore nel codice per una velocità diversa. Gli indirizzi sono configurati ad 11bit

Aprite il terminale seriale dall’editor Arduino e configuratela per una velocità di 115200 baud, nessun controllo di flusso.

Digitate la seguente stringa: @00A0102030405060708 e premete invio.

La stringa è composta di tre parti:

  • @ (Attention) avverte l’interfaccia che una nuova stringa sta arrivando e che deve riallinearsi per un nuovo invio
  • 00A indirizzo di destinazione
  • 01 02 03 04 05 06 07 08 sono gli 8 byte da inviare in formato esadecimale. Ricordiamo che un byte esadecimale è compreso tra 00 e FF.

Se tutte le operazioni sono state effettuate correttamente, l’altra interfaccia riceverà all’indirizzo 0A i byte come nella sequenza mostrata.

Test del codice (Ricezione)

Per il test del codice in ricezione, si effettua l’operazione inversa.

Inviamo all’indirizzo 0B, la stringa 08 07 06 05 04 03 02 01

In ricezione avremo una stringa ASCII formattata in modo analogo alla trasmissione, come di seguito riportato:

Esempio (Canino+LabView)

Un video YouTube dove CAN-ISO dialoga con una centralina industriale con CAN BUS, utilizzando il codice “CANINO” e interfaccia grafica “LabView”:

Conclusioni

Adesso che il codice è testato e siamo in grado di trasmettere/ricevere un pacchetto generico, opportunamente formattato, il prossimo step è utilizzare l’interfaccia con un programma. Nei prossimi tutorial vedremo come utilizzare l’interfaccia con Python, LabVIEW, MATLAB, bash shell ed altri.

Contattateci per farci conoscere le vostre opinioni, o proporci una vostra idea/progetto. Per scriverciinfo(at)rubinolab dot com

Per l’acquisto di CAN-ISO: LINK

Enjoy!

Leave A Comment