Arduino Nano-CAN Module and Micro SD Card Module

Hello,

i have a bigger project.

I already figured how to interface a CAN test board (using the SPI to CAN module when interfacing the test board), which periodically sends out CAN packets.

I am trying to add SD Card module as a datalogger.

Basically:
My board <=> RS232 device
My board <=> CAN module<=CAN test board
?My board <=> Micro SD Card Module?

However the CAN communication stops, when I try to interface the sd card.

Dont mind the RS232 filler, just ignore that…

// demo: CAN-BUS Shield, receive data
#include <mcp_can.h>
#include <SPI.h>
#include <SoftwareSerial.h>

#define rx 7
#define tx 8

//int decMess = 0;
//short unsigned int cursor = 0;
//int pozX[2] = {0,0};
//int pozY[2] = {0,0};
int calcX = 0;
int calcY = 0;
//int *pointerCalcX = &calcX;
//int *pointerCalcY = &calcY;

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];

unsigned int prectenaHodnota = 0;
short int popelnice = 0;
short int cekamCekam = 0;

const byte zacatek = 0xAA;
const byte konec[4]={0xCC,0x33,0xC3,0x3C};
const byte textTrimr[6]={0x54,0x52,0x49,0x4D,0x52,0x3A};
//text pro SAVE, WRITE, ERASE
const byte textSAVE[4]={0x53,0x41,0x56,0x45};
const byte textWRITE[5]={0x57,0x52,0x49,0x54,0x45};
const byte textERASE[5]={0x45,0x52,0x41,0x53,0x45};

SoftwareSerial kom(rx, tx); // RX, TX
MCP_CAN CAN0(10);                               // Set CS to pin 10

void printRxCAN();
void clearObr();
void posli1Byte(byte b1);
void posli2Byte(byte b2[]);
void posliZacatek();
void posliKonec();
void posliSekvenci(byte zprava[]);
void posliPrevedeneCislo(unsigned int cislo);
void DebugLED(int pin);
void DebugTRIMR();
void DebugTlacitkaText();
void DebugTlacitka();
int debugDotyk(bool volba);//FALSE ... 0X72, TRUE ... OX73
//int dotykSouradnice(bool volba);//FALSE ... 0X72, TRUE ... OX73
void charCislaNaHexZpravu(char znak);
void vypisCislice(unsigned int cislo);

void setup()
{
  Serial.begin(115200);
  kom.begin(9600);
  CAN0.begin(CAN_500KBPS);                       // init can bus : baudrate = 500k 
  pinMode(2, INPUT);                            // Setting pin 2 for /INT input
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(5,OUTPUT);
  DebugLED(3);
  DebugLED(4);
  DebugLED(5);
  Serial.println("BOOTOVANI USPESNE");
  clearObr();
  DebugTlacitka();
  DebugTlacitkaText();
  DebugTRIMR();
  Serial.println("=========================================================");
}

void loop()
{
    if(!digitalRead(2))                         // If pin 2 is low, read receive buffer
    {
      CAN0.readMsgBuf(&len, rxBuf);              // Read data: len = data length, buf = data byte(s)
      rxId = CAN0.getCanId();                    // Get message ID
      if(rxId == 0x15F772F5){
        printRxCAN();
        prectenaHodnota = int(rxBuf[0]);//0 az 247
        //itoa(prectenaHodnota, bufferProCislo, 10);
        vypisCislice(prectenaHodnota);
        Serial.print("TRIMR: ");Serial.print(prectenaHodnota);Serial.println();
        popelnice = debugDotyk(true);//FALSE ... 0X72, TRUE ... OX73
        //if(popelnice != 3){popelnice = dotykSouradnice(true);}
        if(popelnice == 1){//1.. ok, 3 .. neni co cist, 2 ... chybne podminky
          Serial.print("SOURADNICE: ");Serial.print(calcX);Serial.print(", ");Serial.print(calcY);Serial.println(" [pix]");
          if(calcX < 50){
            if(( calcY > 0)&&(calcY < 50)){
              Serial.println("ZMACKNUTO TLACITKO 1, SAVE");
              }
            else if(( calcY > 50)&&(calcY < 100)){
              Serial.println("ZMACKNUTO TLACITKO 2, WRITE");
            }
            if(( calcY > 100)&&(calcY < 150)){
              Serial.println("ZMACKNUTO TLACITKO 3, ERASE");
            }
            calcX = 0;calcY = 0;
          }
        }
        Serial.println("=========================================================");

      }
    }
}


void printRxCAN(){
  Serial.print("CAN: ");
  Serial.print("ID: ");
  Serial.print(rxId, HEX);

  Serial.print("  Data: ");
  for (int i = 0; i < len; i++)  // Print each byte of the data
  {
    if (rxBuf[i] < 0x10)  // If data byte is less than 0x10, add a leading zero
    {
      Serial.print("0");
    }
    Serial.print(rxBuf[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  //delay(500);
  }
void clearObr(){
  byte clr=0x52;
  posliZacatek();
  posli1Byte(clr);
  posliKonec();
  }
void DebugLED(int pin){digitalWrite(pin,HIGH);delay(10);digitalWrite(pin,LOW);}
void posliKonec(){for (int i =0; i<sizeof(konec); i++){kom.write(konec[i]);}}
void posliSekvenci(byte zprava[],int delka){for (int i =0; i<delka; i++){posli1Byte(zprava[i]);}}
void posliPrevedeneCislo(unsigned int cislo){
  char bufferProCislo[3]={'0','0','0'};
  itoa(cislo, bufferProCislo, 10);
  if((cislo < 100) && (cislo >=10)){
    charCislaNaHexZpravu('0');
    charCislaNaHexZpravu(bufferProCislo[0]);
    charCislaNaHexZpravu(bufferProCislo[1]);
    }
  else if(cislo < 10){
    charCislaNaHexZpravu('0');
    charCislaNaHexZpravu('0');
    charCislaNaHexZpravu(bufferProCislo[0]);
    }
  else{
  charCislaNaHexZpravu(bufferProCislo[0]);
  charCislaNaHexZpravu(bufferProCislo[1]);
  charCislaNaHexZpravu(bufferProCislo[2]);  
  }
  }
void posliZacatek(){kom.write(zacatek);}
void posli1Byte(byte b1){kom.write(b1);}
void posli2Byte(byte b2[]){posli1Byte(b2[0]);posli1Byte(b2[1]);}
void charCislaNaHexZpravu(char znak){
  switch(znak){
    case ' '://mezera
      posli1Byte(0x20);
      break;
    case '0'://mezera
      posli1Byte(0x30);//muyu k tomuhle pricitat offset, ALE tohle je citelnejsi
      break;
    case '1'://mezera
      posli1Byte(0x31);
      break;
    case '2'://mezera
      posli1Byte(0x32);
      break;
    case '3'://mezera
      posli1Byte(0x33);
      break;
    case '4'://mezera
      posli1Byte(0x34);
      break;
    case '5'://mezera
      posli1Byte(0x35);
      break;
    case '6'://mezera
      posli1Byte(0x36);
      break;
    case '7'://mezera
      posli1Byte(0x37);
      break;
    case '8'://mezera
      posli1Byte(0x38);
      break;
    case '9'://mezera
      posli1Byte(0x39);
      break;                        
    default:
      delay(1);
  }
  }
void vypisCislice(unsigned int cislo){//3mistny cislo


  byte poziceXNum[]={0x00,0xFF};
  byte poziceYNum[]={0x00,0xFF};
  byte zluta[]={0xFC,0x00};
  byte modra[]={0x00,0x1F};


  ////////////////////////////////////////////////////////////////////////////////////////
  posliZacatek();
  posli1Byte(0x98);//ID
  posli2Byte(poziceXNum);
  posli2Byte(poziceYNum);
  posli1Byte(0x00);//00
  posli1Byte(0xC1);//styl zobrazeni
  posli1Byte(0x05);//ID KNIHOVNY
  posli2Byte(zluta);
  posli2Byte(modra);
  posli1Byte(0x00);
  posliPrevedeneCislo(cislo);

  posliKonec();


  
  
  }
void DebugTRIMR(){
  byte poziceX[]={0x00,0xFF};
  byte poziceY[]={0x00,0xCF};
  byte zluta[]={0xFC,0x00};
  byte modra[]={0x00,0x1F};

  posliZacatek();
  posli1Byte(0x98);//ID
  posli2Byte(poziceX);
  posli2Byte(poziceY);
  posli1Byte(0x00);//00
  posli1Byte(0xC1);//styl zobrazeni
  posli1Byte(0x05);//ID KNIHOVNY
  posli2Byte(zluta);
  posli2Byte(modra);
  posli1Byte(0x00);
  posliSekvenci(textTrimr,6);
  posliKonec();  
  }
int debugDotyk(bool volba){//FALSE ... 0X72, TRUE ... OX73
  int decMess = 0;
  bool spravnyStart = false;
  short unsigned int cursor = 1;
  int pozX[2] = {0,0};
  int pozY[2] = {0,0};

  Serial.print("RS232: ");
  while(true){
    decMess = int(kom.read());
    switch(decMess){
      case 170:
        //Serial.print("xAA ");
        spravnyStart = true;
        cursor +=1;
        break;
      case 204:
        calcX=pozX[0]*16*16 + pozX[1];
        calcY=pozY[0]*16*16 + pozY[1];
        //*pointerCalcX = funcCalcX; 
        //*pointerCalcY = funcCalcY;
        /*
        if((calcX < 305)&&(calcY < 230)){DebugLED(10);}
        else if((calcX > 305)&&(calcY < 230)){DebugLED(9);}
        else if((calcX < 305)&&(calcY > 230)){DebugLED(11);}
        else if((calcX > 305)&&(calcY > 230)){DebugLED(12);}

        Serial.print("()()zaznam pozice X= ");Serial.print(pozX[0]);Serial.print(" ");Serial.print(pozX[1]);//zaznam x
        Serial.print(" zaznam pozice Y= ");Serial.print(pozY[0]);Serial.print(" ");Serial.print(pozY[1]);//zaznam y
        Serial.print(" pozice X= ");Serial.print(calcX);Serial.print(" pix, ");//kalkulace x
        Serial.print("pozice Y= ");Serial.print(calcY);Serial.print(" pix()() ");//kalkulace y
        */
        if(spravnyStart == false){Serial.println("WRONG"); cursor = 0; cekamCekam = 0; return 2;}
        Serial.print("xCC ");
        cursor +=1;
        break;
      case 60:
        if(spravnyStart == false){Serial.println("WRONG"); cursor = 0; cekamCekam = 0; return 2;}
        Serial.println("x3C");
        
        cursor = 1;
        decMess = -1;
        cekamCekam = 0;
        DebugLED(3); return 1; //vse ok
        break;      
      case 195:
        if(spravnyStart == false){Serial.println("WRONG"); cursor = 0; cekamCekam = 0; DebugLED(4); return 2; }
        Serial.print("xC3 ");
        cursor +=1;
        break;
      case 51:
        if(spravnyStart == false){Serial.println("WRONG"); cursor = 0; cekamCekam = 0; DebugLED(4); return 2; }
        Serial.print("x33 ");
        cursor +=1;
        break;
      case 114:
        if((volba == true)||(spravnyStart == false)){Serial.println("WRONG"); cursor = 0; cekamCekam = 0; DebugLED(4); return 2; }//chci 0x73
        Serial.print("xAA x72 ");
        cursor +=1;
        //pozX = int(kom.read())*16*16 + int(kom.read())*16; 
        //pozY = int(kom.read())*16*16 + int(kom.read())*16;
        //Serial.print("pozice X = ");Serial.print(pozX);
        //Serial.print(", pozice Y = ");Serial.print(pozY);Serial.print(" ");
        break;
      case 115:
        if((volba == false)||(spravnyStart == false)){Serial.println("WRONG"); cursor = 0; cekamCekam = 0; DebugLED(4);return 2; }//chci 0x72
        Serial.print("xAA x73 ");
        cursor +=1;
        break;    
      case -1://SKIP
        cekamCekam += 1;
        if(cekamCekam == 10){Serial.println("NULL");cekamCekam = 0; DebugLED(5); return 3; }
        break;             
      default:
        if(spravnyStart == false){Serial.println("WRONG"); cursor = 0; cekamCekam = 0; DebugLED(4);return 2;}
        Serial.print(decMess);
        if(cursor == 3){pozX[0] = decMess;}
        if(cursor == 4){pozX[1] = decMess;}
        if(cursor == 5){pozY[0] = decMess;}
        if(cursor == 6){pozY[1] = decMess;}
        cursor +=1;
        Serial.print(" ");
        break;

    }
  }
  }

void DebugTlacitka(){//xx xx yy yy ...4 byty
  byte souradniceA[4]={0x00,0x00,0x00,0x00};//0 0 ... pix
  byte souradniceB[4]={0x00,0x32,0x00,0x32};//50 50
  byte souradniceC[4]={0x00,0x00,0x00,0x32};//0 50
  byte souradniceD[4]={0x00,0x32,0x00,0x64};//50 100
  byte souradniceE[4]={0x00,0x00,0x00,0x64};//0 100
  byte souradniceF[4]={0x00,0x32,0x00,0x96};//50 150

  posliZacatek();//tlacitko 1
  posli1Byte(0x59);
  posliSekvenci(souradniceA,4);
  posliSekvenci(souradniceB,4);
  posliKonec();

  posliZacatek();//tlacitko 2
  posli1Byte(0x59);
  posliSekvenci(souradniceC,4);
  posliSekvenci(souradniceD,4);
  posliKonec();

  posliZacatek();//tlacitko 3
  posli1Byte(0x59);
  posliSekvenci(souradniceE,4);
  posliSekvenci(souradniceF,4);
  posliKonec();
}
void DebugTlacitkaText(){
  byte souradniceX[2]={0x00,0x40};//50 50
  byte souradniceY1[2]={0x00,0x00};//50 50
  byte souradniceY2[2]={0x00,0x32};//50 100
  byte souradniceY3[2]={0x00,0x64};//50 150
  byte zluta[]={0xFC,0x00};
  byte modra[]={0x00,0x1F};

  //const byte textSAVE[4]={0x53,0x41,0x56,0x45};
  //const byte textWRITE[5]={0x57,0x52,0x49,0x54,0x45};
  //const byte textERASE[5]={0x45,0x52,0x41,0x53,0x45};
  //pro rzchle prekopirovani

  posliZacatek();//SAVE
  posli1Byte(0x98);//ID
  posli2Byte(souradniceX);
  posli2Byte(souradniceY1);
  posli1Byte(0x00);//00
  posli1Byte(0xC1);//styl zobrazeni
  posli1Byte(0x05);//ID KNIHOVNY
  posli2Byte(zluta);
  posli2Byte(modra);
  posli1Byte(0x00);
  posliSekvenci(textSAVE,4);
  posliKonec(); 

  posliZacatek();//WRITE
  posli1Byte(0x98);//ID
  posli2Byte(souradniceX);
  posli2Byte(souradniceY2);
  posli1Byte(0x00);//00
  posli1Byte(0xC1);//styl zobrazeni
  posli1Byte(0x05);//ID KNIHOVNY
  posli2Byte(zluta);
  posli2Byte(modra);
  posli1Byte(0x00);
  posliSekvenci(textWRITE,5);
  posliKonec(); 

  posliZacatek();//ERASE
  posli1Byte(0x98);//ID
  posli2Byte(souradniceX);
  posli2Byte(souradniceY3);
  posli1Byte(0x00);//00
  posli1Byte(0xC1);//styl zobrazeni
  posli1Byte(0x05);//ID KNIHOVNY
  posli2Byte(zluta);
  posli2Byte(modra);
  posli1Byte(0x00);
  posliSekvenci(textERASE,5);
  posliKonec(); 
}

This is my code for now, a LOT of it is just RS232. But I am adding the code for the sake of being open.

I got a standard setup of MOSI (D11), MISO (D12), CS (D10) and SCK (D13) to run CAN, I have a display on pins D7 & D8 (RS232).

At this point I am afraid, that I will have to utilise a separate Atmega 328P board just to use it with I2C and have the second board manage the SD Card.

In this case, is it possible to run CAN comm and also log my data into SD card with Arduino Nano?

If possible, could you please direct in right direction?

Example code, reference sites, general knowledge, anything will be helpful or your questions of anything unclear about my question or project.

I am imagining I will use the same SCK, MISO and MOSI pins for the SD card module, but a different CS pin, but that is as far I can imagine myself solving my issue.
SPI is very new to me and I guess this is the most direct way for me to figure out my issue, thanks to you.

Thank you in advance.

I do it with FRAM and a nano so using a SD card should be no problem. Get DuclkDuckGo and search a bit, you should find many similar projects.

As far as what you have I can only guess as you did not post an annotated schematic. <=> I think indicates wiring but no clue as to what goes where.

Your topic has been moved to a more suitable location on the forum as it does not indicate a problem with IDE 2.x.


You should be able to hook up multiple devices to the SPI but; each device needs its own CS pin.

And be careful with cheap SD modules; a number of them don't release the MISO pin. It's worth investing in one from e.g. Pololu (Pololu - Breakout Board for microSD Card with 3.3V Regulator and Level Shifters) or Adafruit (MicroSD card breakout board+ : ID 254 : Adafruit Industries, Unique & fun DIY electronics and kits).

If your board is a 3.3V board a passive one will also do; e.g. Pololu - Breakout Board for microSD Card.

<=> notifies flow of communication

Im sorry, but i dont get what you mean.

Is FRAM a circuit or a library?
I am very confused.

Noted.
Thank you very much
Unfortunately I have to use the cheap blue board, so I guess
It will have to do for now.

That tells me nothing on how it is connected ie. which pin to which pin as displayed on an annotated schematic.

Here is what the web said: Ferroelectric RAM (FRAM) is a type of non-volatile memory that uses a ferroelectric layer to store data, allowing it to retain information even when power is lost. It offers advantages like faster write speeds and higher durability compared to traditional flash memory, but it is generally more expensive. It has no sectors and you can read and write any location in any order. There is no delay for read or write. Here is a link: https://www.mouser.com/c/semiconductors/memory-ics/sram/?mounting%20style=Through%20Hole&organization=32%20k%20x%208

image

:wink:

The link is to mouser and works just fine for me. I tried it on three computers. It is a link to https://www.mouser.com/ c/?q=fram%20memory. Remove the space after com/ I have no idea why it gets denied here.

The link in your original reply now works (after your editing). With the original I got a XSS error from NoScript in Firefox.

It worked on some machines and on this one I got the bad message. I changed the link hoping it would work. Surprisingly I could not copy the the first link and put it in my response, came back Access demoed. I never saw that before on this forum. At least with your help it is now working. Thanks