MBED, Arduino , STN1110 & BT

@2009Prius

now, it is time to start speaking about HW...

thx your wonderfull input for using external files for filters & requests, the project is really well advanced.

next step: prepare a small board for the thing.

basically:


  • mbed .

  • mcp2551 (can transceiver).


  • some connectors.

  • maybe a support for a CR2032 to keep the RTC alive.

  • maybe a support for SDCARD to store logs.

about soft: I am thinking about queuing the received messages, so it will leave plenty of time for decyphering collected data....
 
@priusfan

Wow you are moving so fast! I am truly amazed. :cool:

I just forwarded the e-mail address of my hardware friend to you - he is also having trouble with registration. Once he is registered we can discuss about the hardware in more detail.

One thing came to mind is to have some kind of power saving feature if the device is powered by the 12V from the car.

Another thing is do we have an idea how many people are interested in getting the first iteration of the device? Unlike software which can be easily provided for free, professionally built hardware costs $$$ (to buy parts, buy software to design PCBs, have PCBs made, etc). And we should share the cost so my hardware friend doesn't go broke on this project.

Also do you think BT will be fast enough to transfer all the interesting passive frames? BT is more convenient but I wouldn't sacrifice data for it. Maybe the device can support both BT and USB?
 
...One thing came to mind is to have some kind of power saving feature if the device is powered by the 12V from the car.
...

Just an idea: when car is on, voltage is over 13v : 13.6v to 14.6v. When in first accessory mode near 12v and under.

So just a threshold near 13v could be a simple solution. The 5v regulator could receive a on/off signal on a pin.
 
I would like one, perhaps 2.

I think bluetooth is mandatory. We already have tools with usb connections.
Filters could help us to reduce data transferred and to permit Bluetooth to be enough to transmit remaining data.

Priusfan, do not forget to improve filtering by telling to your software which bytes we need for a message. You could also remove spaces (could be a parameter like the communication speed).

Thank you all, and mainly priusfan, for this project.
 
Just an idea: when car is on, voltage is over 13v : 13.6v to 14.6v. When in first accessory mode near 12v and under.

So just a threshold near 13v could be a simple solution. The 5v regulator could receive a on/off signal on a pin.
good idea...
another possibility : take the + on the cigarette lighter...

regarding PCB, it should be usable using USB and / or BT only if the module is in place.
I don't know yet if the BT interface is fast enough to forward all the interesting passive frames; maybe @460800 bps, if we send compact frames (no spaces)?

regarding the idea of sending only usefull bytes, maybe we would get half the trafic ; that means for each filter and for each request we should associate the bytes numbers to use.
using the same technic as for requests, it could look like:

Code:
7E0 100 03 01 3C 3E 00 00 00 00 [COLOR=Red]3 4 6 7[/COLOR]
where the red numbers are byte numbers.

to do this , we should prepare the tables....
 
et voila encore de la matière de la part de Ken1784
Hi FX,
I have not tested your code, and also I saw you published new program on the mbed site.

Regarding to queue, I saw your captured log.
Quote:
Originally Posted by frenchie
have a look at this capture (made with realterm).

As you may already know, the ID_63B has time stamp and the frame rate is 2 frames/second.
Your log tells me your capture rate is approx 67%.

Please refer to following xls file about my analysis.
http://www.geocities.jp/clubman246/image/63B.xls

I tested message queuing, and the can.attach ISR routine works as expected.

Please refer to following sample programs.
CAN_MONITOR_INTERRUPT.zip for USB port terminal log
CAN_CHANFS_BUF_debug.zip for SD card log

Following is a sample log for 100sec period.
http://www.geocities.jp/clubman246/image/100sec.zip

Following is my analysis about ID_0B4 data which is approx 41.5 frames/sec.
http://www.geocities.jp/clubman246/i...0B4_100sec.xls

On the SD card version, some SD access time last more than 150 frames period, so we need a lot of buffer memory.
However, the queue using can.attach ISR works, and no frame is missing (100% capture rate), I believe.
smile.gif


Regards,
Yoshi
ses liens sont inaccessibles, je lui ai demandé de m'envoyer le contenu par mail...
edit 13:32
received from Yoshi the code for queuing; I will implement it asap.


Code:
// CAN_MONITOR using can2.attach with ring buffer and filtering
// 2012/Apr/07 ym1784

#include "mbed.h"
#include "CAN.h"

Serial pc(USBTX, USBRX); // tx, rx
DigitalOut led2(LED2);
// CAN2 on mbed pins 29(CAN_TXD) and 30(CAN_RXD) using MCP2551.
CAN can2(p30, p29);
CANMessage can_MsgRx;
Timer timer;

// function prototypes
void CAN2_wrFilter (uint32_t id);
void can_check(void);

#define BUFFER_SIZE 32  // buffer size must be power of 2
#define BUFFER_MASK ( BUFFER_SIZE - 1)
unsigned int second[BUFFER_SIZE];
unsigned short can_id[BUFFER_SIZE];
unsigned char msg_length[BUFFER_SIZE];
unsigned char data[8][BUFFER_SIZE];
unsigned int head = 0;
unsigned int tail = 0;

int main() {
    pc.baud(921600);
    pc.printf("CAN_MONITOR using can2.attach, 921600 bps\r\n");

    // 500kbit/s
    can2.frequency(500000);

    CAN2_wrFilter(0x0B4);   // trip distance, vehicle speed
    CAN2_wrFilter(0x3B9);   // coolant temperature
    CAN2_wrFilter(0x3D3);   // fuel usage
    CAN2_wrFilter(0x498);   // engine rpm
    CAN2_wrFilter(0x612);   // fuel tank level
    CAN2_wrFilter(0x63B);   // time stamp

    timer.reset();
    timer.start();
    can2.attach(&can_check);
    int tmptail;

    while (1) {
        // read CAN messages from the buffer, then send it to the pc
        if ( head != tail ) {               // new message is available
            tmptail = (tail + 1) & BUFFER_MASK;
            pc.printf("%08X,", second[tmptail]);
            pc.printf("t%03X%d", can_id[tmptail], msg_length[tmptail]);
            for (char i=0; i<msg_length[tmptail]; i++) {
                pc.printf("%02X", data[i][tmptail]);
            } // for
            pc.printf("\r\n");
            tail = tmptail;                 // update tail after data sent
        } // if head != tail
    } // while
} // main

//--------------------------------------------
//  setup acceptance filter for CAN controller 2
//  original http://www.dragonwake.com/download/LPC1768/Example/CAN/CAN.c
//  simplified for CAN2 interface and std id (11 bit) only by ym1784
//--------------------------------------------
void CAN2_wrFilter (uint32_t id)  {
//    ..................................................
} // CAN2_wrFilter

// CAN2 read using intterupt and ring buffer
void can_check(void) {
    int temp_head;

    while ( can2.read(can_MsgRx) ) {
        temp_head = (head + 1) & BUFFER_MASK;
        if ( temp_head == tail ) {
            fprintf(stderr, "buffer overflow\r\n");
            fprintf(stderr, "head = %d\r\n", head);
            fprintf(stderr, "tail = %d\r\n", tail);
        }       // error
        second[temp_head] = timer.read_us();
        can_id[temp_head] = can_MsgRx.id & 0xFFF;
        msg_length[temp_head] = can_MsgRx.len;
        for (char i=0; i<can_MsgRx.len; i++) {
            data[i][temp_head] = can_MsgRx.data[i];
        } // for
        head = temp_head;   // update head after data stored
        // toggle led2
        led2 = !led2;
    } // while
} // can_check
 
Dernière édition:
ring buffer = FIFO

the ring buffer suggested by ken1784 is really problematic because it is a LIFO (Last In First Out) queue.

8)
in case of multiframes, we get the risk to read the last frame before the others, and with the actual logic, the app will believe it received the full answer and so, send a corrupted message.

I imagine 2 possibilities:

:eek:
1) change the type of queue to use a FIFO (First In First Out) to preserve the chronology.

:-?
2) when receiving frames belonging to a multiframe answer (normally, first byte starting with 2), store the 7 bytes at the right place (depending on the lower nibble), and only when the byte count is reached, send the complete answer... this is a bit tricky...but my preferred solution...



edit 11/04
I wrote something completely wrong: this a ring buffer so it is a FIFO queue
http://en.wikipedia.org/wiki/Circular_buffer
 
Dernière édition:
Fifo is absolutely necessary
PCM need to receive the data as soon as they are available and in the right order, it does integration calculations.
 
et voila encore de la matière de la part de Ken1784
ses liens sont inaccessibles, je lui ai demandé de m'envoyer le contenu par mail...

J'ai pû télécharger le xxxxx 63B.xls (pas essayé les autres) Mais il a fallu attendre longtemps avant d'avoir la fenêtre windows qui permet de dire où on veut que le fichier aille sur le dd.
 
Dernière édition:
I confirm that the links to Ken1784's files appear to be all expired.

@priusfan if you have a copy of the files maybe you could upload here as attachments? Thanks!


About power saving, how about supply power from the USB? If the computer goes to sleep or the USB cable unplugged then the device powers off.
 
I would prefer that the power come from the car. That way we could have later another project where the device can work standalone and store data on a sd card. But we can start with a usb powered device.
 
Hello from Japan

Hello all,
Thank you priusfan for inviting me to this forum.

I would like to report a bug on my ring buffer code posted at #82 of this thread.
Found we need "volatile" keyword to work the buffer properly, so please change the source as follows;
Code:
volatile unsigned int head = 0;
volatile unsigned int tail = 0;
Regards,
Yoshi@Japan

PS. I am not familiar with French, and I am not a native English speaker. So, please forgive me about my poor English.
 
Welcome Yoshi@Japan! Glad to "see" you here! :cool:
 
Hello, Ken, Hello Yoshi, Hello Yokohama, Hello Japan. <= that is real poor English: just one word. :-D

Et bienvenue (Welcome) :jap:
 
おはようございます Yoshi

I tested quickly this morning with the volatile, but the program locks after a few frames; I had no time to investigate...

I will go more deeply in the detail this evening or tomorrow.

Yesterday evening, I had the visit from our famous friend Murphy: one of the CAN wire was broken on my board... what is funny : I got sometimes a few frames.

for sharing easily documents regarding this project, I opened a FTP

server : priusfan.info
port: 21
user: u39344557-mbed
pwd: mbed2012

it works fine with filezilla, it was tested by 2009Prius.

to make a link to a file named test123.zip on this ftp,
the url should be: (remove spaces)
h t t p://priusfan.info/canmonitor/mbed/test123.zip
 
Dernière édition:
Ring Buffer

after looking on the web, I think I will try this:

declarations
Code:
#define BUFFER_SIZE 128  // buffer size must be power of 2
#define BUFFER_MASK ( BUFFER_SIZE - 1)
volatile unsigned int rb_write_pointer = 0; // ring buffer write pointer
volatile unsigned int rb_read_pointer = 0;  // ring buffer read pointer
volatile unsigned int rb_data_size = 0;     // ring buffer number of entries
unsigned int second[BUFFER_SIZE];
unsigned short can_id[BUFFER_SIZE];
unsigned char msg_length[BUFFER_SIZE];
unsigned char data[8][BUFFER_SIZE];
add entries
Code:
void can_check(void) {

    while ( can2.read(can_MsgRx) ) {

        rb_write_pointer++ ;                //  increase write_pointer
        rb_write_pointer &= BUFFER_MASK;    //  loop if at end of array
        rb_data_size++ ;                    // ring buffer number of entries
       
        if ( rb_write_pointer == rb_read_pointer && rb_data_size == BUFFER_SIZE) {  // buffer overflow
            fprintf(stderr, "buffer overflow\r\n");
            fprintf(stderr, "head = %d\r\n", rb_write_pointer);
            fprintf(stderr, "tail = %d\r\n", rb_read_pointer);
        }       // error
        // add entries in the ring buffer
        second[rb_write_pointer] = timer.read_us();
        can_id[rb_write_pointer] = can_MsgRx.id & 0xFFF;
        msg_length[rb_write_pointer] = can_MsgRx.len;
        for (char i=0; i<can_MsgRx.len; i++) {
            data[i][rb_write_pointer] = can_MsgRx.data[i];
        } // for
                
        led2 = !led2; // toggle led2
    } // while
} // can_check
read entries
Code:
    while (1) {
        // read CAN messages from the buffer, then send it to the pc
        if ( rb_data_size > 0 ) {               // new message is available
            rb_read_pointer++;                      // position to next
            rb_read_pointer &= BUFFER_MASK;         //  loop if at end of array
            rb_data_size--;                         // update nbr of entries in the ring buffer

            pc.printf("%d,", rb_read_pointer);
            pc.printf("%d,", rb_write_pointer);
            pc.printf("%d,", rb_data_size);
            pc.printf("%08X,", second[rb_read_pointer]);
            pc.printf("t%03X%d", can_id[rb_read_pointer], msg_length[rb_read_pointer]);
            for (char i=0; i<msg_length[rb_read_pointer]; i++) {
                pc.printf("%02X", data[i][rb_read_pointer]);
            } // for
            pc.printf("\r\n");

            // we store in w_vars the results : it is not funny to manage all these [][]
            int w_id=can_id[rb_read_pointer];
            int w_len=msg_length[rb_read_pointer];
            char w_data[8];
            for (int i=0; i<w_len; i++) {
                w_data[i]=data[i][rb_read_pointer];
            } // for
 
I would prefer that the power come from the car. That way we could have later another project where the device can work standalone and store data on a sd card. But we can start with a usb powered device.

But the main reason is: we want it works using bluetooth only.
But we can accept to use usb just for power, and for an additional data connection, and for upgrading the software or parameters.
 
Regarding power saving/power source: I worry BT is not fast enough to catch up with all the interesting passive messages for Gen 2 Prius. So I had assumed USB will be necessary. But I understand it is more convenient to use BT without having to deal with the USB cable, and also for some applications it is desirable to save data in SD card without any live connection to a PC. Maybe the device can be designed to get its power from either USB or the car 12V, like OBDLink does.

Regarding ring buffer: It may not improve performance measurably for the mbed but I think it is in general good practice to arrange the data array for efficient memory access: instead of
Code:
unsigned char data[8][BUFFER_SIZE];
we change it to
Code:
unsigned char data[BUFFER_SIZE][8];
and change the indexing in the program correspondingly, for example
Code:
data[rb_write_pointer][i]

Also a dumb question: What's the difference between
Code:
#include "USBSerial.h"  
//Virtual serial port over USB 
USBSerial serial;
and
Code:
Serial pc(USBTX, USBRX);
? Why are we using the latter? How is BT connected to this?
 
in mbed, there 4 UART, I use pc & bt; pc is in fact usbserial, so I will proceed to some cleaning....

following your suggestion, I changed to
unsigned char data[BUFFER_SIZE][8];
you are right, it is more logical.

I have now something working fine (there is a small bug detecting end of multiframe, it will be solved tonight).

a nice info: for gen3, using filters and requests, realterm announces less than 10000cps, that means using BT @115kbps should work fine.

@thierryb: could you prepare an excel sheet containing for each ID the interesting bytes, so you could try to transmit only these.
 
I will.
You will have it this weekend.
It will be based on PCM.

One more suggestion based on our discussions:
for each passive id, we can give a parameter N to tell to the device to drop N-1 frame and to transmit only the frame N, and repeat. So we could reduce bandwidth too.
 
hello

we shall soon get the visit here from ccdisce.*

he can probably help us for the hardware part.
here is an extract from a mail from him:
I have been trying to get the obdlink working with 2009Prius to fix the instability problem which seems to be with the hardware. I have also looked at the ELM Electronics chip and it is stable but the data upload rate is maxed out at 500KBaud and causes BUFFER FULL errors.
They are not too receptive to fiixng the problems.


Your project looks interesting as it adds BT interface which I tested on a Sparkfun Clone that I created when I was testing 2009Prius SW..
Yes I agree that mbed is expensive but it brings a lot of features we do not need such as EtherNET and a host USB but it is easy to download as it includes a downloader in the form of the preprogrammed , presumably by the mpad group, ARM Cortex M7.

Could you set up a membership with ccdisce as pseudo and a default password.

I had a look at the SKPank device that you mentioned. It seems quite similar to the Arduino version but he has other demo boards.

One that I have looked at in the past:

http://mbed.org/users/WiredHome/notebook/Smartboard-baseboard/

which has most of what you have specified. I actually have a mbed and 2 blank baseboards on order as I was thinking on working on a bird feeder/ squirrel immobilizer

I am interested enough in this project to spend some of my own money on it, It is not necessary for you or the Prius Touring Club to spend money at this stage and this is provided that I have full hardware rights to the final device.

Winston.
* to have an idea about ccdisce, have a look there: http://priuschat.com/forums/gen-ii-prius-modifications/88694-prius-ect-spoofer-mcu-controlled.html
 
Nice, he used microchip pic. :victoire: That's the one I have in my bms.

I am a happy customer of his device which has been working well in my car for 7 months.

Back to mbed, since it has two CAN channels, is there any advantage to use both, one just listens (like ATMA, but with filters if desirable) and the other just do the requests?

@priusfan: I looked at the most recent code on the ftp site, please make some minor changes:
Code:
#include "sstream"
->
Code:
#include <sstream>
for styling.
Code:
ss>>hex>>id>>freq;
->
Code:
ss>>hex>>id>>dec>>freq;
so that freq can be specified in decimal, not hex, in the file request.txt. Thanks!

By the way I am having trouble understanding this:
Code:
// next req, find msg_ReqIdx
                        do {
                            reqTable[msg_ReqIdx].fcnt++;
                            if (reqTable[msg_ReqIdx].fcnt >= reqTable[msg_ReqIdx].freq) {
                                reqTable[msg_ReqIdx].fcnt = 0;
                            } // endif
                            msg_ReqIdx++;
                            if (msg_ReqIdx > reqNumTbl) {
                                msg_ReqIdx = 0;
                            } // endif
                        } while (reqTable[msg_ReqIdx].fcnt != 0);
I assume it works as intended (request according to freq specification)?
 
@2009Prius

regarding the use of 2 CAN, I do not see any interest,
my first idea was to use 2 STN1110 on arduino platform:
one for sending requests,
other one just doing atma.
But it was necessary to use 3 UART at high speed...

thx for correcting my mistakes.....
:oops:

regarding search for nextrequest, the result is OK, I don't remember exactly how it works, (I tested the loops on paper and was astonished...) but it is ok.
(I wrote something like this in VB 3 years ago when using a tactrix).

the original comes from Moon Light from mbed.org, there was a small error corrected by ken1784.

on the ftp, I uploaded:
the original from Moon Light : CANUSB30 (DO NOT USE or you will get red triangle).
a small dev for checking the sequence of requests : simul_req
 
@priusfan

No not mistake, just different style. :cool:

I don't have mbed yet so I modified the simul_req to print to screen. Now I understand it better. The "freq" is not frequency, but inverse frequency (period). So a request with freq = 1 would run ten times more often than a request with freq = 10.

I also found a minor typo:
Code:
if (msg_ReqIdx > req_NumTbl)
should be changed to
Code:
if (msg_ReqIdx >= req_NumTbl)
 
Pages vues depuis le 20 Oct 2005: 314,207,126
Retour
Haut Bas