|
|
View previous topic :: View next topic |
Author |
Message |
Wolf
Joined: 23 Sep 2011 Posts: 32
|
CAN Bus Problem |
Posted: Sat Jan 04, 2014 5:28 pm |
|
|
I have created some CAN bus boards based on this training system (which is sold by CCS) http://www.ccsinfo.com/product_info.php?products_id=CAN-Bus-24-kit
I'm using MCP2515 CAN controllers connected to dsPIC30F4011 exactly the same way as it is in the trainer (all the pins of each chip are wired the same way as it is in the demo board to make things easier). Below is a picture of how 2 of the boards are connected. The board on the top is what I'm using as a master and the board on the bottom is the board I am using as a slave. The connectors on the right hand sides of the boards each have 2, 240 ohm resistors in parallel to make 120 ohm terminators that are connected to CAN HI/LOW on each side.
https://dl.dropboxusercontent.com/u/53843754/IMG_0468.JPG (I made a link to the picture cause it fills up the screen in this thread)
My objective is simple, when I push the 2 test buttons on the bottom of the master board (which is located in between the 20 pin connector) I am trying to make the buzzer on the slave board turn on/off. Essentially I am trying to get 2 Node B's on that training board (supplied by CCS) to talk to each other
This is my test code for the master:
Code: |
#include <30F4011.h>
#DEVICE DSPIC30F4011
#DEVICE *=16 ICD=TRUE ADC=10
#fuses PR,FRC_PLL16,NOWDT
#use delay(clock=117.92M)
#use rs232(baud=9600,UART1A)
#use i2c(master, sda=PIN_F2, scl=PIN_F3)
#include <can-mcp251x.c>
#define BLUE_STAT1_LED PIN_E4
#define YELLOW_STAT2_LED PIN_E2
#define BUZZER PIN_E1
#define TOGGLE_SWITCH1 PIN_D2
#define TOGGLE_SWITCH2 PIN_F1
#define TOGGLE_SWITCH3 PIN_F0
#define WRITE_register_C_ID 0x300
void main() {
unsigned int32 rx_id;
unsigned int8 int8RxLength,int8Buffer[8];
struct rx_stat rxstat;
set_tris_b(0x0011);
set_tris_c(0x6000);
set_tris_d(0x000F);
set_tris_e(0x0100);
set_tris_f(0x0013);
can_init();
while(TRUE) {
if (input_state(TOGGLE_SWITCH1) == 0) {
int8Buffer[0] = 0x3A;
int8Buffer[1] = 0x20;
can_putd(WRITE_REGISTER_C_ID, int8Buffer, 2, 1, TRUE, FALSE);
output_high(BLUE_STAT1_LED);
}
else {
output_low(BLUE_STAT1_LED);
}
if (input_state(TOGGLE_SWITCH3) == 0) {
int8Buffer[0] = 0x3A;
int8Buffer[1] = 0x10;
can_putd(WRITE_REGISTER_C_ID, int8Buffer, 2, 1, TRUE, FALSE);
output_high(YELLOW_STAT2_LED);
}
else {
output_low(YELLOW_STAT2_LED);
}
}
}
|
This is my code for the slave:
Code: |
#include <30F4011.h>
#DEVICE DSPIC30F4011
#DEVICE *=16 ICD=TRUE ADC=10
#fuses PR,FRC_PLL16,NOWDT
#use delay(clock=117.92M)
#use rs232(baud=9600,UART1A)
#use i2c(master, sda=PIN_F2, scl=PIN_F3)
#include <can-mcp251x.c>
#define BLUE_STAT1_LED PIN_E4
#define YELLOW_STAT2_LED PIN_E2
#define BUZZER PIN_E1
#define TOGGLE_SWITCH1 PIN_D2
#define TOGGLE_SWITCH2 PIN_F1
#define TOGGLE_SWITCH3 PIN_F0
#define WRITE_register_C_ID 0x300
void main() {
unsigned int32 rx_id;
unsigned int8 rx_len,buffer[8];
struct rx_stat rxstat;
set_tris_b(0x0011);
set_tris_c(0x6000);
set_tris_d(0x000F);
set_tris_e(0x0100);
set_tris_f(0x0013);
can_init();
while(TRUE) {
if(can_getd(rx_id, &buffer[0], rx_len, rxstat)) {
if ((rx_id == WRITE_REGISTER_C_ID) && (buffer[0] == 0x3A)) {
if (buffer[1] == 0x20) {
output_high(BUZZER);
output_high(BLUE_STAT1_LED);
output_low(YELLOW_STAT2_LED);
}
if (buffer[1] == 0x10) {
output_low(BUZZER);
output_low(BLUE_STAT1_LED);
output_high(YELLOW_STAT2_LED);
}
}
}
}
}
|
They were both coded using MPLabX so to beat that problem of compiler not accepting the program, the can-mcp251x.c had to be made excluded from the compiler build which was mentioned to be in another forum thread.
The problem is, they don't communicate properly. In fact once I plug the slave into the master, the buttons on the master no longer function and requires a power cycle reset to get it going again. Could someone please tell me what I am doing wrong? All I am trying to do is make a buzzer turn on/off with 2 buttons pressed at a master just to get basic communication going between the 2. I later want to add 2 more boards to the CAN bus network but cannot do that till I can simply get 2 going first.
Thank you everyone |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 05, 2014 1:41 am |
|
|
Quote: | I have created some CAN bus boards.
In fact once I plug the slave into the master, the buttons on the master no
longer function and requires a power cycle reset to get it going again. |
You made your own boards and they don't work. You should probably
post a schematic of the board(s) and also post a schematic of the
connections between the boards. |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Jan 05, 2014 2:21 am |
|
|
Quote: |
You made your own boards and they don't work. You should probably
post a schematic of the board(s) and also post a schematic of the
connections between the boards. |
The reason why I didn't post schematic's is because I don't know how to give them to you in a compatible format, every time I try to PDF the files they look like garbage in this PDF https://dl.dropboxusercontent.com/u/53843754/CAN%20Bus%20Interface.pdf
Here is the MultiSim 11.0 file that I used to make the schematic which is the best I can do, I'm afraid I just don't know how to make it any better sorry https://dl.dropboxusercontent.com/u/53843754/CAN%20Bus%20Node.ms11
Here is the CAN bus book that the schematic was modeled off of, please see page 54 node B https://dl.dropboxusercontent.com/u/53843754/Development%20Kit%20for%20the%20CANBus%2024%20Exercise%20Book.pdf
As for the connections between the boards, all the plugs are the same:
1) Shield => (bare conductor)
2) Ground => (black)
3) CAN low => (white)
4) CAN high => (green)
5) +12 volts => (red)
And they connect from board to board in that order. They are connected together at the green sockets on the left and right side of each board. On the left side pin 1 (shield) is at the top, and the left side, pin 1 is at the bottom. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 05, 2014 8:51 pm |
|
|
Your schematic isn't really usable. If I try to zoom in on it, the pin
numbers go out of focus. I can't use your ms11 file. I don't have
a reader for it.
I'll try to work on it without a schematic. All I can do is try to make it
work with two 18F2580 PICs and MCP2551 Can bus transceivers mounted
on two PicDem2-Plus boards. I don't have your 30F4011 PICs.
I can work on it on Monday. |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Jan 05, 2014 9:45 pm |
|
|
I have posted the CAN bus 24 book, if you look at the node schematic on it, its connected exactly the same way as it is in the book. I did it like that so that I could get help easier.
I also came across a test code in some other thread http://www.ccsinfo.com/forum/viewtopic.php?t=29627&start=3 and modified it slightly to work with this hardware. It compiled and downloaded nicely but I have had little success with it.
Code: |
#include <30F4011.h>
#DEVICE DSPIC30F4011
#DEVICE *=16 ICD=TRUE ADC=10
#fuses PR,FRC_PLL16,NOWDT
#use delay(clock=117.92M)
#use rs232(baud=9600,UART1A)
#use i2c(master, sda=PIN_F2, scl=PIN_F3)
#include <can-mcp251x.c>
#define BLUE_STAT1_LED PIN_E4
#define YELLOW_STAT2_LED PIN_E2
#define BUZZER PIN_E1
#define TOGGLE_SWITCH1 PIN_D2
#define TOGGLE_SWITCH2 PIN_F1
#define TOGGLE_SWITCH3 PIN_F0
#define BOARD1_ID 24
#define BOARD2_ID 25
// Uncomment this line to compile code for Board #1.
// Comment it out to compile for Board #2.
#define BOARD1 1
void main() {
char chrTestLoop;
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int8 rx_len;
int8 buffer[8];
set_tris_b(0x0011);
set_tris_c(0x6000);
set_tris_d(0x000F);
set_tris_e(0x0100);
set_tris_f(0x0013);
can_init();
#ifdef BOARD1 // For Board #1
printf("Startup Text\n\r");
while(1) {
//buffer[0] = getc(); // Wait for a character
for (chrTestLoop = 0; chrTestLoop < 4; chrTestLoop++) {
output_high(BUZZER);
delay_ms(100);
output_low(BUZZER);
delay_ms(500);
switch (chrTestLoop) {
case 0: { buffer[0] = 'A'; break;}
case 1: { buffer[0] = 'B'; break;}
case 2: { buffer[0] = 'C'; break;}
case 3: { buffer[0] = 'D'; break;}
}
printf ("Sending Char %c\n\r", buffer[0]);
}
// Transmit it to board #2.
can_putd(BOARD2_ID, buffer, 1, 1, 1, 0);
buffer[0] = 0; // Clear the buffer byte
// Wait for the char to be echoed back.
while(!can_kbhit());
if(can_getd(rx_id, buffer, rx_len, rxstat)) {
if (rx_id == BOARD1_ID) { // Is it for this board ?
putc(buffer[0]); // If so, display the char
printf ("Received Char %c\n\r", buffer[0]);
switch (buffer[0]) {
case 'A': {
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'B': {
output_high(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'C': {
output_low(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
case 'D': {
output_high(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
default: {
printf ("Unknown Char %c\n\r", buffer[0]);
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
}
}
}
}
#else // For Board #2
while(1) {
if(can_kbhit()) { // Message available ?
// If so, get the message.
if(can_getd(rx_id, buffer, rx_len, rxstat)) {
if(rx_id == BOARD2_ID) { // Is it for this board ?
// If so, echo back the character.
output_high(BUZZER);
delay_ms(100);
output_low(BUZZER);
can_putd(BOARD1_ID, buffer, 1, 1, 1, 0);
printf ("Received Char %c\n\r", buffer[0]);
switch (buffer[0]) {
case 'A': {
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'B': {
output_high(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'C': {
output_low(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
case 'D': {
output_high(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
default: {
printf ("Unknown Char %c\n\r", buffer[0]);
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
}
}
}
}
}
#endif
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 05, 2014 11:58 pm |
|
|
You are testing two things at once.
1. You are testing your hardware setup which consists of the two boards,
the connections between the boards, power supply, etc.
2. Your program.
You should only test one thing at a time.
First, prove that your boards work OK. Test each board in MCP2515
loopback mode. This post contains sample loopback code:
http://www.ccsinfo.com/forum/viewtopic.php?t=41683&start=10
Then test the two boards with that program that loops them together
and lets you send characters through the boards and displays the
output on a serial terminal window.
When you have that all working, then try your own test code.
You have this hugely complicated program with all these buffers, cases,
etc., and you should be doing initial testing with a very simple program. |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Tue Jan 07, 2014 10:52 am |
|
|
Alright, I will give it a try tonight. That program looks promising, and I appologies for the long delay in my reply. I will post back here if I have any further problems, thank you! |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Wed Jan 08, 2014 8:21 am |
|
|
Thank you very much, that loop back program was successful for one of the boards that I tested, and since the 3 others are built the exact same way, it's safe to assume that they should function as well (but I will test them out anyway)
Code: |
#include <30F4011.h>
#DEVICE DSPIC30F4011
#DEVICE *=16 ICD=TRUE ADC=10
#fuses PR,FRC_PLL16,NOWDT
#use delay(clock=117.92M)
#use rs232(baud=9600,UART2)
#use i2c(master, sda=PIN_F2, scl=PIN_F3)
#include <can-mcp251x.c>
#define EXT_CAN_CS PIN_B1
#define EXT_CAN_SI PIN_B2
#define EXT_CAN_SO PIN_B4
#define EXT_CAN_SCK PIN_E5
//=================================
void main(void)
{
int32 can_id;
int8 can_data[8];
int8 can_length;
struct rx_stat rxstat;
printf("Begin\n\r");
can_init();
can_set_mode(CAN_OP_LOOPBACK);
printf("Starting\n\r");
can_data[0] = 0x55;
while(1)
{
if(can_putd(42, can_data, 1, 3, TRUE, FALSE))
printf("Tx OK, ");
else
printf("Tx failed, ");
while(!can_kbhit());
if(can_getd(can_id, &can_data[0], can_length, rxstat))
printf("Rx OK, ");
else
printf("Rx failed, ");
printf("Rx data = %x \n\r", can_data[0]);
delay_ms(500);
}
}
|
The problem was in the following defines:
Code: |
#define EXT_CAN_SI PIN_B2
#define EXT_CAN_SO PIN_B4
#define EXT_CAN_SCK PIN_E5
|
And the fix was to manually open "can-mcp251x.c" and edit the defines inside that function header. I don't know why it didn't like the external defines but modifying the defines inside can-mcp251x driver fixed the problem so that the loop back would function.
Last edited by Wolf on Wed Jan 08, 2014 11:19 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Jan 08, 2014 8:34 am |
|
|
The obvious reason is that defines have to be made _before_ the code uses them. You show them being set after the file is loaded.....
Lets expand a bit further.
There are two approaches to include files. If you look at things like the USB examples. they have defines like the connection sense pin 'bracketed' with #ifdef/#endif endif statements, so if something is 'predefined' this is used instead of the version in the include file.
On the second approach, there is no such testing.
For the first approach, you have to define ahead of including the file.
For the second, you have to change the define in the file.
In neither case will defining _after_ the file work.....
Best Wishes |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Wed Jan 08, 2014 11:26 am |
|
|
Oh and another thing is (perhaps you might know), I guess I got a little bit over zealous about saying the board worked, I noticed when I looked at the screen that I would see most of the time. I would see Tx Ok, Rx Ok shoot all over my screen but there would be the odd hit where you might see Tx failed on my terminal window. It wasn't all the time, but I would say maybe every 5th or 6th time it would show up. Is it normal that communication wont be perfect every single time in the MCP2515? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 09, 2014 5:53 pm |
|
|
Quote: | but there would be the odd hit where you might see Tx failed on my
terminal window. It wasn't all the time, but I would say maybe every 5th
or 6th time it would show up. Is it normal that communication wont be
perfect every single time in the MCP2515? |
It should not do that. There is something wrong that needs to be fixed.
Quote: | #use delay(clock=117.92M) |
The can-mcp251x.c file uses the #use spi() library code. It defaults to
software SPI. The #use spi() statement doesn't specify a baud rate,
so it will use the maximum possible. You are running the PIC at a very
high clock rate. The mcp2515 has a maximum SPI clock speed of 10 MHz.
It's possible that you are exceeding that limit. You could add a BAUD
parameter to the #use spi() statement and set it for 5 MHz.
Make a test program and measure the SCLK speed with an oscilloscope.
Just make a while loop and repeatedly call spi_xfer() and write something.
Measure the bit period of one SCLK cycle to make sure it's not less than
100 ns (i.e, a 10 MHz clock). |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Thu Jan 09, 2014 10:33 pm |
|
|
Interesting, I am only running at that baud because all the example codes in the CAN bus 24 exercise book say to follow that code. It puzzles me as to how they got it to work if its such a high frequency on the SPI bus. Anyway, I will try this out on Saturday and post back here with my results.
Thanks |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sat Jan 11, 2014 12:15 pm |
|
|
Ya it looks like it was an SPI clock speed problem. I am now able to see
Code: |
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
Tx OK, Rx OK, Rx data = 55
|
I tested out all my boards, and I am able to see the activity above on all of them. So I continued to the next step, trying to get 2 boards to talk to each other, now I am running into problems. As soon as I get 2 boards connected, the system freezes up.
I modified a test program....
Code: |
#include <30F4011.h>
#DEVICE DSPIC30F4011
#DEVICE *=16 ICD=TRUE ADC=10
#fuses PR,FRC_PLL16,NOWDT
#use delay(clock=117.92M)
#use rs232(baud=9600,UART2) //UART1A)
#use i2c(master, sda=PIN_F2, scl=PIN_F3)
#define EXT_CAN_CS PIN_B1
#define EXT_CAN_SI PIN_B2
#define EXT_CAN_SO PIN_B4
#define EXT_CAN_SCK PIN_E5
#include <can-mcp251x.c>
#define BLUE_STAT1_LED PIN_E4
#define YELLOW_STAT2_LED PIN_E2
#define BUZZER PIN_E1
#define TOGGLE_SWITCH1 PIN_D2
#define TOGGLE_SWITCH2 PIN_F1
#define TOGGLE_SWITCH3 PIN_F0
#define BOARD1_ID 24
#define BOARD2_ID 25
// Uncomment this line to compile code for Board #1.
// Comment it out to compile for Board #2.
#define BOARD1 1
void main() {
char chrTestLoop;
struct rx_stat rxstat;
int32 rx_id;
int32 tx_id;
int8 rx_len;
int8 buffer[8];
set_tris_b(0x0011);
set_tris_c(0x6000);
set_tris_d(0x000F);
set_tris_e(0x0100);
set_tris_f(0x0013);
printf("Startup Text\n\r");
can_init();
#ifdef BOARD1 // For Board #1
while(1) {
buffer[0] = getc(); // Wait for a character
printf("Input %c character\n\r", buffer[0]);
// Transmit it to board #2.
can_putd(BOARD2_ID, buffer, 1, 1, 1, 0);
printf("Placed %c out CAN Buffer...\n\r", buffer[0]);
buffer[0] = 0; // Clear the buffer byte
printf("Cleared buffer...\n\r");
// Wait for the char to be echoed back.
while(!can_kbhit());
printf("CAN bus network activity detected\n\r");
if(can_getd(rx_id, buffer, rx_len, rxstat)) {
if (rx_id == BOARD1_ID) { // Is it for this board ?
putc(buffer[0]); // If so, display the char
printf ("Received Char %c\n\r", buffer[0]);
switch (buffer[0]) {
case 'A': {
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'B': {
output_high(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'C': {
output_low(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
case 'D': {
output_high(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
default: {
printf ("Unknown Char %c\n\r", buffer[0]);
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
}
}
}
}
#else // For Board #2
while(1) {
if(can_kbhit()) { // Message available ?
// If so, get the message.
if(can_getd(rx_id, buffer, rx_len, rxstat)) {
if(rx_id == BOARD2_ID) { // Is it for this board ?
// If so, echo back the character.
output_high(BUZZER);
delay_ms(100);
output_low(BUZZER);
printf ("Received char %c\n\r", buffer[0]);
can_putd(BOARD1_ID, buffer, 1, 1, 1, 0);
printf ("Sent char %c through buss\n\r", buffer[0]);
switch (buffer[0]) {
case 'A': {
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'B': {
output_high(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
case 'C': {
output_low(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
case 'D': {
output_high(YELLOW_STAT2_LED);
output_high(BLUE_STAT1_LED);
break;
}
default: {
printf ("Unknown Char %c\n\r", buffer[0]);
output_low(YELLOW_STAT2_LED);
output_low(BLUE_STAT1_LED);
break;
}
}
}
}
}
}
#endif
}
|
I get this on my terminal window
Code: |
Startup Text
Input B character
Placed B out CAN Buffer...
Cleared buffer...
|
After that, it's stuck and I do see activity on CAN Hi and CAN Low with a scope |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 12, 2014 3:35 pm |
|
|
Are you sure you compiled the two different versions of the code for
Board #1 and Board #2 ? Did you burn them into the correct boards ?
Did you put labels on the boards, identifying them as #1 and #2 ?
Did you use your programmer to verify that the code that's burned into
each board is actually the correct code for that board ?
Are the boards connected in the correct order, as shown in this post ?
http://www.ccsinfo.com/forum/viewtopic.php?t=29627&start=7
Like this:
Code: |
rs232 CAN
PC <-----> Board #1 <---> Board #2
|
Also, I notice you have loaded up the simple program given in the link
above, with all of your switch-case code, printf statements, etc.
Why not keep it simple until you get the test code working ? |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Jan 12, 2014 9:38 pm |
|
|
Well that code is simple, it just turns on some LED's if I get an A, B, C or D across the CAN bus network. And if the board gets that character it beeps, it gives me more visibility as to whats going on.
The board is connected like this...
Code: |
rs232 CAN
PC <-----> Board1 <---> Board2
|
Yes the board is labeled and yes the code does get burned into the pics, but I think maybe the issue is some kind of hardware reset problem. The program starts to do funny things like lock up when you add more then 1 board to the CAN network. Adding capacitors around the dsPIC on one of the boards seemed to kind of make things run better but not quite. It's strange, its like I have to completely power off the system in order to download programs into it sometimes.
I have also added a cap to the MCLR pin which kind of helps make it accept programs better. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|