1
\$\begingroup\$

I have been working on a CAN bus project. It is a project from the book Advanced micro controller projects by Dogan. It is a temperature sensor CAN bus project. As you know, the project can't be simulated because MCP2551 is not available in Proteus, so I implemented it in`` hardware according to the schematic in the book.

Enter image description here

I implemented the circuit on two breadboards using a CAN bus of twisted pairs. I used PIC18F458 with its built-in CAN module. The length of the bus is less than 500 cm. When I tested it, it only displayed the welcome message on the LCD.I tested the code for transmission of characters. It worked but for temperature it doesn't show data.

Here is the code of the collector node.

//unsigned char Can_Init_Flags, Can_Send_Flags,dt,len, Can_Rcv_Flags;
unsigned short init_flag, send_flag,len, read_flag;volatile int dt;
char SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg, txt[4];
long id, mask;
int bitvalue;
float vout, temperature; int flag;

#define d portb.b0

void adc_setting()
{
  adcon0 = 0x00;
  adcon1 = 0x80;
  intcon = 0xc0;
  pie1.adie = 1;
  pir1.adif = 0;
}

void interrupt()
{
  if (pir1.adif)
  {
    pir1.adif = 0;
    adcon0.adon = 0;
    flag = 1;
    adcon0.adon = 1;
    adcon0.go_done = 1;
  }
}

void main()
{
  //Portc=0x08;
  TRISA = 0xFF; // PORTA are inputs
  //TRISB = 0x08; // RB2 is output, RB3 is input
  //
  // Configure A/D converter
  //
  //ADC_Init();
  adc_setting();
  adcon0.adon = 1;
  adcon0.go_done = 1;


  //ADCON1 = 0x80;
  //
  // CAN BUS Timing Parameters
  //
  SJW = 1;
  BRP = 1;
  Phase_Seg1 = 6;
  Phase_Seg2 = 7;
  BRP = 1;
  Prop_Seg = 6;

  init_flag= _CAN_CONFIG_SAMPLE_THRICE &
             _CAN_CONFIG_PHSEG2_PRG_ON &
             _CAN_CONFIG_STD_MSG &
             _CAN_CONFIG_DBL_BUFFER_ON &
             _CAN_CONFIG_VALID_XTD_MSG &
             _CAN_CONFIG_LINE_FILTER_OFF;
              send_flag  = _CAN_TX_PRIORITY_0 &
              _CAN_TX_XTD_FRAME &
              _CAN_TX_NO_RTR_FRAME;
               read_flag=0;

     //
     // Initialise CAN module
     //
  CANInitialize(SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg,init_flag );
  //
  // Set CAN CONFIG mode
  //
  CANSetOperationMode(_CAN_MODE_CONFIG,0xFF);
  mask = -1;
  //
  // Set all MASK1 bits to 1's
  //
  CANSetMask(_CAN_MASK_B1, mask, _CAN_CONFIG_XTD_MSG);
  //
  // Set all MASK2 bits to 1's
  //
  CANSetMask(_CAN_MASK_B2, mask, _CAN_CONFIG_XTD_MSG);
  //
  // Set id of filter B1_F1 to 500
  //
  CANSetFilter(_CAN_FILTER_B1_F1,500,_CAN_CONFIG_XTD_MSG);
  //
  // Set CAN module to NORMAL mode
  //
  CANSetOperationMode(_CAN_MODE_NORMAL, 0xFF);

  // Program loop. Read the temperature from analog temperature sensor

  while(1) // Endless loop
  {
    //
    // Wait until a request is received
    //
    dt = 0;
    while (!dt) dt = CANRead (&id, i, &len, read_flag);
    if (id == 500 && i[0]=='T')
    {
      if (flag==1)
      {
        bitvalue = (adresh<<8)+adresl;
        vout = bitvalue * 0.00488;
        temperature = vout / 0.0100;

        i[0] = temperature;
        id = 3; // Identifier
        CANWrite (id, i, 1, send_flag); // send temperature
      }
    }
  }
}

And here is the code of display node

float temperature; unsigned char i[8];

unsigned short init_flag, send_flag, dt, len, read_flag;

char SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg, txt[4];

long id, mask;

sbit LCD_RS at RC4_bit;

sbit LCD_EN at RC5_bit;

sbit LCD_D4 at RC0_bit;

sbit LCD_D5 at RC1_bit;

sbit LCD_D6 at RC2_bit;

sbit LCD_D7 at RC3_bit;

sbit LCD_RS_Direction at TRISC4_bit;

sbit LCD_EN_Direction at TRISC5_bit;

sbit LCD_D4_Direction at TRISC0_bit;

sbit LCD_D5_Direction at TRISC1_bit;

sbit LCD_D6_Direction at TRISC2_bit;

sbit LCD_D7_Direction at TRISC3_bit;

// End LCD module connections

void main()
{
    TRISC = 0; // PORTC are outputs (LCD)

    //TRISB = 0x08; // RB2 is output, RB3 is input

    //
    // CAN BUS Parameters

    SJW = 1;

    BRP = 1;

    Phase_Seg1 = 6;

    Phase_Seg2 = 7;

    Prop_Seg = 6;

    Init_Flags = _CAN_CONFIG_SAMPLE_THRICE &
                     _CAN_CONFIG_PHSEG2_PRG_ON &
                     _CAN_CONFIG_STD_MSG &
                     _CAN_CONFIG_DBL_BUFFER_ON &
                     _CAN_CONFIG_VALID_XTD_MSG &
                     _CAN_CONFIG_LINE_FILTER_OFF;
    Send_Flags = _CAN_TX_PRIORITY_0 &
                     _CAN_TX_XTD_FRAME &
                     _CAN_TX_NO_RTR_FRAME;

    Can_Rcv_Flags = 0;

    //
    //
    // Initialize CAN module
    //
    //

    CANInitialize(SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg, init_flag);

    // Set CAN CONFIG mode
    //

    CANSetOperationMode(_CAN_MODE_CONFIG, 0xFF);

    mask = -1;

    // Set all MASK1 bits to 1's

    CANSetMask(_CAN_MASK_B1, mask, _CAN_CONFIG_XTD_MSG);

    // Set all MASK2 bits to 1's
    //

    CANSetMask(_CAN_MASK_B2, mask, _CAN_CONFIG_XTD_MSG);

    //
    // Set id of filter B2_F3 to 3

    //

    CANSetFilter(_CAN_FILTER_B2_F3, 3, _CAN_CONFIG_XTD_MSG);

    //
    // Set CAN module to NORMAL mode
    //

    CANSetOperationMode(_CAN_MODE_NORMAL, 0xFF);


    // Configure LCD

    Lcd_init(); // LCD is connected to PORTC

    Lcd_Out(1,1,"CAN BUS"); // Display heading on LCD

    Delay_ms(1000); // Wait for 2 seconds


    //
    // Program loop. Read the temperature from Node:COLLECTOR and display

    // on the LCD continuously
    //
    while(1) // Endless loop
    {
        Lcd_Out(1,1,"Temp = "); // Display "Temp = "
        //
        // Send a message to Node:COLLECTOR and ask for data
        //
        i[0] = 'T'; // Data to be sent
        id = 500; // Identifier
        CANWrite(id, i, 1, send_flag); // Send 'T'
        //
        // Get temperature from node:COLLECT
        //
        dt = 0;
        while(!dt)
            dt = CANRead(&id, i, &len, &read_flag);

        if(id == 3)
        {
            temperature = i[0];
            ByteToStr(temperature,txt); // Convert to string
            Lcd_Out(1, 8, txt); // Output to LCD
            Delay_ms(1000); // Wait 1 second
        }
    }
}

The temperature is not displayed at all. I tried changing the code a few times, but the problem remains the same. I checked the tx pin of the collector node on a digital oscilloscope. It didn't show anything. It isn't transmitting any data. Why is it not transmitting any data?

Is there a problem with my code? Should I remove the request condition in the transmission node and just write data to the second node and disable the filter?

\$\endgroup\$
  • 1
    \$\begingroup\$ If you are looking for help, a good way to start would be by posting the code the way you wrote enter code here unsigned char temperature,i[8]; \$\endgroup\$ – MaNyYaCk Dec 31 '16 at 15:41
  • 1
    \$\begingroup\$ You have a function called interrupt(), but there's no indication that it is associated with any actual hardware interrupt. If this function is never executed, then flag is never set and nothing gets transmitted. \$\endgroup\$ – Dave Tweed Jan 3 '17 at 21:51
1
\$\begingroup\$
I implemented the circuit on two breadboards using a CAN bus of twisted pairs.

You still have to tie the grounds of both microcontrollers together. CAN is tolerant of some common mode variation of the bus lines, but they can't be arbitrarily floating. Put another way, you need to connect the two nodes with three wires, the twisted pair for the CANH and CANL lines, and a ground wire.

\$\endgroup\$
  • \$\begingroup\$ Sir my circuit is ok.I mean i connected the node with twisted pairs.And both nodes are grounded according to the schematic.The LCD display shows the welcome message but does not show the temperature.I think there is a problem with the code.The tx pin of the first node does not show any voltage in digital oscilloscope. \$\endgroup\$ – Ammar Jan 1 '17 at 15:40
  • \$\begingroup\$ @Ammar If you don't use a dedicated signal ground, then the supply ground will be used as reference. If there's a high difference in potential between the systems, it will obviously not work. But even if there isn't, you'll pick up all kinds of EMI noise from the supply ground. \$\endgroup\$ – Lundin Jan 3 '17 at 9:17
  • \$\begingroup\$ Sir I tested the same code for transmission of charcters.It worked but does not display temperature.I don't know why is dedicated ground needed here?The circuit is built on two breadboards joined together.And length of the bus is less than 300 cm.I don't think there will be emi for such distance \$\endgroup\$ – Ammar Jan 3 '17 at 16:40
  • \$\begingroup\$ Does ADC built in function work in this project? \$\endgroup\$ – Ammar Jan 3 '17 at 19:16
1
\$\begingroup\$

This code doesn't make any sense:

    dt = 0;

    while(!dt);

        dt = CANRead(&id, b, &len, &Can_Rcv_Flags);

        if(id == 3)
        {
            temperature = b[0];

            ByteToStr(temperature,txt); // Convert to string

            Lcd_Out(1, 8, txt); // Output to LCD

            Delay_ms(1000); // Wait 1 second
        }
    }

I believe you are tricked by your own indention. The final brace above belongs to the for(;;) - because the while loop does not have any braces, it only has an empty ; null statement and no loop body.

So the lines dt = 0; while(!dt); are useless, because dt is always zero at this point.

You probably meant to write

while(!dt)
{
  dt = CANRead(&id, b, &len, &Can_Rcv_Flags);
}

This would be why you should always use braces after every control or loop statement in your code, and never place semicolons at the same line as one. Good compilers warn against such semicolons.


Otherwise, if this was intentional despite the weird indention and dt is a variable shared with an ISR, your code is still incorrect because dt wasn't declared as volatile and the compiler may optimize it incorrectly. See this:

http://www.embedded.com/electronics-blogs/cole-bin/4418638/When-to-use---and-not-use---the-volatile-keyword

\$\endgroup\$
  • \$\begingroup\$ Yeah I also thought that DT isn't being used in the code.What is the purpose of it?You are right about the while loop.I already made changes to it.You talked about keyword volatile.My compiler mikroc didn't give any error.Shouldn't I just remove it? \$\endgroup\$ – Ammar Jan 3 '17 at 16:32
  • 1
    \$\begingroup\$ @Ammar The note about volatile only applies if the variable is used by an ISR. If the posted code is the full code, then that doesn't apply here. But still, you need to know how volatile works when writing any form of embedded software. \$\endgroup\$ – Lundin Jan 4 '17 at 7:53
  • \$\begingroup\$ Sir I don't know if it is used in the ISR.But DT is not used.So why not replace it with other variable \$\endgroup\$ – Ammar Jan 4 '17 at 14:34
  • 1
    \$\begingroup\$ @Ammar It is clearly used here: dt = CANRead(.... It's just the loop that's incorrect. \$\endgroup\$ – Lundin Jan 4 '17 at 15:39
  • \$\begingroup\$ Sir the temperature is not displayed using this code.What do u think is the problem?Can temperature data be sent in float or char data type? \$\endgroup\$ – Ammar Jan 4 '17 at 16:42
0
\$\begingroup\$

My guess is that one of these messages is not received correctly. The message filtering here is important: you have configured the receive filter so that both of the messages you are sending are extended types (29-bit id). Can you verify that you send the messages as an extended frames and the CAN modules are initialized with extended frames enabled? Your code is not completely self explanatory about this.

Standard and extended messages in CAN-bus are completely different. If you send a standard message with an id of 5 and you have configured the receive filter to receive extended messages with an id of 5, you will not receive anything.

\$\endgroup\$
  • \$\begingroup\$ Am I wrong or are you initializing the display's CAN module with uninitialized init_flag and sending the messages with uninitialized send_flag arguments? You declare Can_Init_Flags and Can_Send_Flags variables which are not defined. Here might be a problem. \$\endgroup\$ – olltsu Jan 4 '17 at 21:42
  • \$\begingroup\$ Sir I transmitted a char variable for instance 'B' with the same code.It worked but temperature data is not displayed on LCD. \$\endgroup\$ – Ammar Jan 4 '17 at 21:57
  • \$\begingroup\$ This means the filters are configured correctly \$\endgroup\$ – Ammar Jan 4 '17 at 21:58
  • \$\begingroup\$ How to find out if the filters are enabled in standard and extended frames? \$\endgroup\$ – Ammar Jan 4 '17 at 22:07
  • \$\begingroup\$ it is init_flags not CAN_init_flags.It is a mistake.the mistake is in display node.But the problem remains. \$\endgroup\$ – Ammar Jan 4 '17 at 22:19

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.