# Getting Curtis data into computer



## khaffner (Jul 22, 2020)

I'm involved in a project where we're converting a diesel boat to electric. All the electronics and the motor work on the bench, no questions there. My main task in this is getting the data about the rpm, power and everything else from the Curtis 1236 controller, into a raspberry pi. I'm having trouble where to start. What pins on the controller and pi should connect, is something between necessary, what software do I need? Say I want to log the rpm to a file every second, as a start. Thanks!


----------



## frodus (Apr 12, 2008)

Do you know much about CAN?


----------



## khaffner (Jul 22, 2020)

Pretty much nothing. But I'm comfortable with electronics and Linux, if that helps.


----------



## frodus (Apr 12, 2008)

Start looking into CAN. There's some info on google on CAN for the Curtis inverters if you look around. They use CAN open, so you'd have to do a lot of protocol implementation. Not much is available over Serial other than what displays on their cheapo little display.


----------



## Isaac97 (Jun 3, 2019)

CAN is a automotive bidirectional address-based bus. Each "frame" has an ID, length, and data bytes.
A Pi can use CAN if you add an MCP2515 module (cheap on Amazon etc.).
Python works well for CAN since there are lots of libraries you can use.

Software side:
Send an NMT message to put the inverter into state 5. Repeat at least every 100ms.
ID:0x000
DLC:2
Data: 0x01 0x00

Response will be sent with ID=0x700 + node ID. You need the Node ID for the next step (remember it's all in hex).

Then send PDO1 and PDO2 requests.
PDO1
ID:0x200
DLC:8
Data: Whatever

PDO2
ID:0x300
DLC:8
Data: Whatever

Have fun decoding the responses 


Hardware:
[quick-guide] CAN bus on raspberry pi with MCP2515 - Raspberry Pi Forums

This sets up the MCP2515 CAN interface as a network connection, then you can use can-utils to see what's going on.

Try the python-can library on your Pi. It should work well.

-Isaac

EDIT Also check this thread out: Curtis 1234 and CAN bus


----------



## khaffner (Jul 22, 2020)

Thanks! Would this work? RS485 CAN HAT for Raspberry Pi Via SPI Onboard 1 x CAN Bus MCP2515 Transceive... | eBay


----------



## frodus (Apr 12, 2008)

Yes that HAT should work.

Concerning the CAN messaging, I think there's some if you search online for Curtis + 1236 or 1238 + Canopen. I recall there being some things people have done with RPi already.


----------



## khaffner (Jul 22, 2020)

While I'm waiting for the HAT to arrive, I'd like to make sure I understand the wiring between it and the controller. Page 22 of the controller manual is about CAN wiring. 
1: Is it correct to connect pin 21 (CAN Term H) and 34 (CAN Term L) on the controller together with short wires? If yes, what does this accomplish? Enabling CAN?
2: Pin 23 (CANH) and 35 (CANL) correspond nicely with the CANH and CANL shown on the HAT here:








Just connect pin 23 to CANH and 35 to CANL? Anything else I should connect?

Thanks for all the help


----------



## Isaac97 (Jun 3, 2019)

1. Yes, that is correct. Connecting those will enable the CAN termination resistors. I don't remember if I did that but my CAN adapter was terminated already.
Termination resistors place a load on the drivers -- I'm not really sure why this is necessary, it probably has something to do with making the signals cleaner (since there's a current flowing). It is definitely needed though, if you skip resistors the signals look really nasty and reflect around inside the wires and also don't work.

2. Correct. Also hook the CAN_GND_ISO to the Curtis ground 

-Isaac


----------



## khaffner (Jul 22, 2020)

Hello again!
There has been some progress. I could not make the HAT work, so I also bought a USB CAN adapter. I like this better, as I can try it out on my laptop (also with Linux) before involving the Pi.

We had some wiring to do. The AmpSeal plug for the controller did not have any CAN wires, so I had to order the pins, wire them up and get them in there according to the manual. A lot of time spent on waiting for packages, 

Today, we started actually trying to read something from the CANL and CANH. But first, we checked the resistance of the CANL and CANH from the controller when everything was powered off, 120 Ohms. And when connected to the USB CAN adapter, 60 Ohms. so far so good. We then turned the rig on and measured the voltage across ground (battery minus) and CANH. 2.8V. And across ground and CANL, 2.1V. We used a (high quality) voltmeter, so these would be averages. But since it's not 2.5V, it's a good sign right? 2.5V would mean no messages, if I understand the canbus correctly.

So I connected the adapter and I think the problem lies here. I struggle to find a guide specific to the adapter I purchased, so I can only try various guides. Most of them say roughly the same things. I tried this one. I could skip step 2, the rest went through without errors. But the candump said nothing, and ifconfig said no packets were received. This is where I'm stuck. I tried a few CAN speeds, still nothing. 

What should I try next?


----------



## [email protected] (Nov 28, 2020)

Isaac97 said:


> CAN is a automotive bidirectional address-based bus. Each "frame" has an ID, length, and data bytes.
> A Pi can use CAN if you add an MCP2515 module (cheap on Amazon etc.).
> Python works well for CAN since there are lots of libraries you can use.
> 
> ...


Sir, @Isaac97
I have the hardware setup ready!
I also tested the CAN communication between RPi and arduino which works fine!!
I used CAN python in Pi and seedstudio mcp2515 library in arduino.
Now for connecting Pi to curtis do I need to use the python library called canopen?
Do I need to write VCL code for curtis?
Can you please explain how do I recieve data in RPi?
Thank you


----------



## Isaac97 (Jun 3, 2019)

Fortunately, VCL is unnecessary.
Python canopen is not necessary either - I am not familiar with it, but it might make the job easier.
You should find some documentation on the CANOpen protocol and learn how to send a NMT message to all nodes. That will tell you which address to use for the next few steps.

-Isaac


----------



## [email protected] (Nov 28, 2020)

Isaac97 said:


> Fortunately, VCL is unnecessary.
> Python canopen is not necessary either - I am not familiar with it, but it might make the job easier.
> You should find some documentation on the CANOpen protocol and learn how to send a NMT message to all nodes. That will tell you which address to use for the next few steps.
> 
> -Isaac


Thank you so much sir, where can I find resources regarding sending nmt messages to nodes and finding out address? Is there any documentation from curtis regarding the same? Now I tried to scan nodes and found one of the node being successfully scanned and printed by python canopen. How do I proceed?


----------



## Isaac97 (Jun 3, 2019)

PDO - Process Data Objects - CanOpen - ByteMe
NMT Protocol - Network Managment - CanOpen - ByteMe

Should be a good start


----------



## [email protected] (Nov 28, 2020)

Isaac97 said:


> PDO - Process Data Objects - CanOpen - ByteMe
> NMT Protocol - Network Managment - CanOpen - ByteMe
> 
> Should be a good start


Thank you sir


----------



## [email protected] (Nov 28, 2020)

Isaac97 said:


> PDO - Process Data Objects - CanOpen - ByteMe
> NMT Protocol - Network Managment - CanOpen - ByteMe
> 
> Should be a good start


Hi sir , @Isaac97
Thank you so much for this very useful link.
I wanted to clarify some doubts regarding process data objects.
I will set the NMT function of the curtis to be always operational as only then my node (curtis) will accept a PDO message.
So if I consider RPi as server and curtis as a client , Should I send a Transmit PDO or a Recieve PDO from RPi?
I also checked with curtis datasheet which has both transmit and recieve PDO indexes.
Assuming I am sending a Recieve PDO from RPi , will the curtis be automatically configured to send back a Transmit PDO?
Thank you


----------



## Isaac97 (Jun 3, 2019)

I don't quite remember, try them both maybe? 
The request I remember using was 0x200 + node ID for PDO1.
-Isaac


----------



## [email protected] (Nov 28, 2020)

Isaac97 said:


> I don't quite remember, try them both maybe?
> The request I remember using was 0x200 + node ID for PDO1.
> -Isaac


Just to confirm that you didn't have to do anything with respect to VCL , you just sent data from a device to curtis and curtis responded to you back!
Thank you so much sir


----------



## Isaac97 (Jun 3, 2019)

Great! My pleasure 
-Isaac


----------



## [email protected] (Nov 28, 2020)

Isaac97 said:


> Great! My pleasure
> -Isaac


Thank you again!


----------



## khaffner (Jul 22, 2020)

Hello again!
I've been trying a lot with slcand, ip, ifconfig and such on my computer with the motor running slowly and the CANbus seemingly correctly connected. Whatever I try, nothing comes out. There are those CAN speeds (-s1 (20kbps) to -s6 (500kbps)), whether or not it is can or vcan, and maybe more variables I'm not aware of. I've tried all the CAN speeds. My USB-CAN adapter has an "ACT" LED, I assume this stands for activity. This lights a solid orange/red.

I'm starting to suspect the controller does not send CAN signals at all. The controller was pulled from a G-Wiz/REVAi which did not use the CAN interface, so I would not be surprised if CAN is turned off in the controller. As far as I know, the only way to enable it is to buy the 1313 or 1314, which cost hundreds of dollars. Is this the case?

I'm also looking at the Curtis 840. I still want the data into my own computer, but the 840 points to the fact that the serial connection also can give me the information I want. If this is the route to go, can you guys point me to how I can read and parse the serial data from the Curtis 1236 on a computer?

Thanks


----------



## [email protected] (Nov 28, 2020)

You can buy an Arduino and a cheap SPI to CAN module and connect it with arduino.
SPI 2 CAN module
A general example to send a NMT message via arduino to curtis to put it into operational state.

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

const int spiCSPin = 10;
int ledHIGH    = 1;
int ledLOW     = 0;

MCP_CAN CAN(spiCSPin);

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

    while (CAN_OK != CAN.begin(CAN_500KBPS,MCP_8MHz))
    {
        Serial.println("CAN BUS init Failed");
        delay(100);
    }
    Serial.println("CAN BUS Shield Init OK!");
}

unsigned char stmp[2] = {0,0};
 
void loop()
{
  stmp[0]=0x01;//Operational state
  stmp[1]=0x00;//target node ==> set 0x00 for all nodes
  Serial.println("In loop");
  CAN.sendMsgBuf(0x00, 0, 2, stmp);// COB-ID, 0 for standard ID and 1 for extended ID, 2 is the data length , stmp is the data
  delay(120);//heartbeat message rate
}
```
A general example to send a SDO message via arduino to curtis to retrieve Key Switch Voltage


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

const int spiCSPin = 10;

MCP_CAN CAN(spiCSPin);


void recv()
{
  unsigned char len = 0;
  unsigned char buf[8];
  unsigned char a,b,c;
  int a1,b1,c1;
  if(CAN_MSGAVAIL == CAN.checkReceive())
    {
        CAN.readMsgBuf(&len, buf);

        unsigned long canId = CAN.getCanId();

        Serial.println("-----------------------------");
        Serial.print("Data from ID: 0x");
        Serial.println(canId, HEX);

        for(int i = 0; i<len; i++)
        {
            Serial.print(buf[i]);
            Serial.print("\t");
            a = buf[4];
            b = buf[5];
         

         }
        a1 = (int)a;
        b1 = (int)b;
        c1 = b1 << 8 | a1 ;
        Serial.print("\nKey_switch_voltage:");
        Serial.println(c1);
        Serial.println();
    }
}

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

    while (CAN_OK != CAN.begin(CAN_500KBPS,MCP_8MHz))
    {
        Serial.println("CAN BUS init Failed");
        delay(100);
    }
    Serial.println("CAN BUS Shield Init OK!");
}

unsigned char stmp[8] = {0,0,0,0,0,0,0,0};
 
void loop()
{
  stmp[0]= 0x40; //Read Dictionary Object
  stmp[1]= 0x4D;//second eight bytes of hex value(sub index)
  stmp[2]= 0x32;// first eight bytes of hex value (index)
  stmp[3]= 0x00;
  stmp[4]= 0x00;
  stmp[5]= 0x00;
  stmp[6]= 0x00;
  stmp[7]= 0x00;
  Serial.println("In loop");
  CAN.sendMsgBuf(0x626, 0, 8, stmp);//... , 0 for standard ID and 1 for extended ID, ... , stmp is the data
  delay(100);// timeout
  recv();
}
```


----------

