0

So to try and speed up my project, I have moved from using two UNO's to a UNO on the receive side, and teensy 3.6 on the sender side. However, no dice. The UNO doesn't receive any data or even try to print it. I have found it gets to the line;

if(!digitalRead(CAN0_INT))

and then the program won't proceed. I have swapped out the teensy and run the same code on an UNO again on the sender to check all the connections work and it is fine, as soon as I plug in the teensy no messages are received.

As far as I can tell the MCP2515 module does not work on 3.3V, so I'm wondering if it is that. So, my plan is to power the MCP2515 from a 5V source, and drop the voltage on the interrupt and MISO line to 3.3V so the teensy is safe.

However I am unsure on how to do this, and I also need a quick fix as i'm away this afternoon until January and don't have a logic converter to hand. I have seen you can use a voltage divider to reduce voltage but will that be an issue as that solution is apparently only for slow signals?

Any other thoughts on why this setup won't work are welcome. So just incase I have added my code that works on UNO's but not on teensy. My only other thought why this won't work is that teensy 3.6 already has CAN bus and the code is not compatible?

Sender

// CAN Send Example
//

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

const int MPU_addr = 0x68; // I2C address of the MPU-6050

float lastTimeSent;
const float intervalSendMs = 0.000001; // Send period in milliseconds
float currMillis;

int16_t AccX, AccY, AccZ, Tmp, GyX, GyY, GyZ; 
uint8_t dataArray[32];
uint8_t data1[8], data2[8];
int Switch = 7;
const int AS_Pin = 10;

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

void setup()
{
    Serial.begin(115200);

    initializeMCP2515();

    pinMode(Switch, OUTPUT);
    digitalWrite(Switch, HIGH);

    initializeMPU9250();

}

void loop()
{
    currMillis = millis();

    if ((currMillis - lastTimeSent) >= intervalSendMs)
    {
        lastTimeSent += intervalSendMs;

        readFromMPU9250();

        //MPU_Data_to_CAN_Array();

        convertDataToPackets();

        // Send the two frames; if the first sending is successful send also the second, otherwise abort
        // send data frame 1:  ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
        // send data frame 2:  ID = 0x101, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send
        if (CAN0.sendMsgBuf(0x100, 0, 8, data1) == CAN_OK)
            CAN0.sendMsgBuf(0x101, 0, 8, data2);
    }

                  Serial.print(currMillis);
                  Serial.print("\t");
                  Serial.print(AccX);
                  Serial.print("\t");
                  Serial.print(AccY);
                  Serial.print("\t");
                  Serial.print(AccZ);
                  Serial.print("\t");
                  Serial.print(GyX);
                  Serial.print("\t");
                  Serial.print(GyY);
                  Serial.print("\t");
                  Serial.println(GyZ);


}

//===================================================================================
//                                  FUNCTIONS                                             
//===================================================================================
void initializeMCP2515()
{
    // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
    if(CAN0.begin(MCP_ANY, CAN_1000KBPS, MCP_16MHZ) == CAN_OK)
        Serial.println("MCP2515 Initialized Successfully!");
    else
        Serial.println("Error Initializing MCP2515...");

    CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted
}

void initializeMPU9250()
{
  pinMode(AS_Pin, OUTPUT);
  digitalWrite(AS_Pin, HIGH);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
  SPI.setDataMode(SPI_MODE0);
  SPI.begin();
}

void readFromMPU9250()
{
      digitalWrite(AS_Pin, LOW); 
  SPI.transfer(0x80|0x3B);

  for(int i = 0; i < 14; i++){
  dataArray[i] = SPI.transfer(0);
  }
  digitalWrite(AS_Pin, HIGH);
delay(50);

AccX = dataArray[0]<<8|dataArray[1];
AccY = dataArray[2]<<8|dataArray[3];
AccZ = dataArray[4]<<8|dataArray[5];
GyX = dataArray[8]<<8|dataArray[9];
GyY = dataArray[10]<<8|dataArray[11];
GyZ = dataArray[12]<<8|dataArray[13];
}

void convertDataToPackets()
{
    long2Byte(currMillis, 0, data1);
    int2Byte(AccX, 4, data1);
    int2Byte(AccY, 6, data1);

    int2Byte(AccZ, 0, data2);
    int2Byte(GyX, 2, data2);
    int2Byte(GyY, 4, data2);
    int2Byte(GyZ, 6, data2);
}

void int2Byte(int16_t input, int pos, uint8_t *data)
{
    for (int i = 0; i < 2; i++)
    {
        data[i + pos] = ((input >> (i * 8)) & 0xff);
    }
}

void long2Byte(uint32_t input, int pos, uint8_t *data)
{
    for (int i = 0; i < 4; i++)
    {
        data[i + pos] = ((input >> (i * 8)) & 0xff);
    }
}

/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

Receiver

// CAN Receive Example
//

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

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

char msgString[128];                        // Array to store serial string
uint32_t TimeMicro;
int16_t AccX, AccY, AccZ, GyX, GyY, GyZ;

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


void setup()
{
    Serial.begin(115200);

    initializeMCP2515();

    Serial.println("MCP2515 Library Receive Example...");
    Serial.println("waiting for data");
    receivedFirstFrame = 0;
    Serial.println("data recived?");
}

void loop()
{
    if(!digitalRead(CAN0_INT))
    {
        // Received a message
        if (CAN0.readMsgBuf(&rxId, &len, rxBuf) == CAN_OK)
        {
            // Note: the above line is not like in the examples, but looking at the code the
            // function may return if no message was in the queue, so I think this is safer

            // Let's check if it is one of the known messages
            switch (rxId)
            {
            case 0x100:
                { // Received first frame
                    // Decode the content and store that the first frame was received
                    decodeFirstFrame(rxBuf);
                    receivedFirstFrame = 1;
                    Serial.print(TimeMicro);
                    Serial.print("\t");
                    Serial.print(AccX);
                    Serial.print("\t");
                    Serial.print(AccY);

                }
                break;
            case 0x101:
                if (receivedFirstFrame)
                { // Received second frame after a first frame
                    // Decode the content
                    decodeSecondFrame(rxBuf);

                  Serial.print("\t");
                  Serial.print(AccZ);
                  Serial.print("\t");
                  Serial.print(GyX);
                  Serial.print("\t");
                  Serial.print(GyY);
                  Serial.print("\t");
                  Serial.println(GyZ);

                    //printDataToSerial();

                    receivedFirstFrame = 0;
                }
                break;
            }
        }
    }

    TimeMicro = 0;
    AccX = 0;
    AccY = 0;
    AccZ = 0;
    GyX = 0;
    GyY = 0;
    GyZ = 0;
}

//===================================================================================
//                                  FUNCTIONS                                             
//===================================================================================

void initializeMCP2515()
{
    // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
    if(CAN0.begin(MCP_ANY, CAN_1000KBPS, MCP_16MHZ) == CAN_OK)
        Serial.println("MCP2515 Initialized Successfully!");
    else
        Serial.println("Error Initializing MCP2515...");

    CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted

    pinMode(CAN0_INT, INPUT);                            // Configuring pin for /INT input
}

void decodeFirstFrame(uint8_t *rxBuff)
{
    TimeMicro = byte2Double(TimeMicro, 0, rxBuff);
    AccX = byte2Int(AccX, 4, rxBuff);
    AccY = byte2Int(AccY, 6, rxBuff);
}

void decodeSecondFrame(uint8_t *rxBuff)
{
    AccZ = byte2Int(AccZ, 0, rxBuff);
    GyX = byte2Int(GyX, 2, rxBuff);
    GyY = byte2Int(GyY, 4, rxBuff);
    GyZ = byte2Int(GyZ, 6, rxBuff);
}


uint32_t byte2Double(uint32_t output, int pos, uint8_t data[4]){
      for (int i = 0; i < 4; i++)
    {
      output += ((uint32_t)data[i + pos]) << (i * 8);
    }
    return output;
}

int16_t byte2Int(int16_t output, int pos, uint8_t data[2]){
      for (int i = 0; i < 2; i++)
    {
      output += ((int16_t)data[i + pos]) << (i * 8);
    }
    return output;
}
/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

Thanks

  • search for arduino logic level converter – Jaromanda X Dec 24 '18 at 9:32
  • That is my plan for when I'm back but I wanted to test the setup before I left. Is there no quick fixes just so I can test for 10 seconds? – Ross Hanna Dec 24 '18 at 9:35
  • Why should a voltage divider only for slow signals? Is the parasite capacitance of the lines really that big? – chrisl Dec 24 '18 at 9:51
  • 2
    The MCP2515 works fine at 3.3V. Check the Electrical Characteristics in the datasheet, VDD: 2.7V to 5.5V – Majenko Dec 24 '18 at 11:02
  • Thanks majenko, the seller I bought it from had it down as 5V only so must have made a mistake. The voltage divider question I'm not sure on. There seems to be a lot of conflicting views on methods for reducing voltage for sensors. I had read somewhere for things like spi voltage dividers weren't fast enough – Ross Hanna Dec 26 '18 at 9:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.