Drive mode selector using Arduino

Post Reply
User avatar
catphish
Posts: 954
Joined: Fri Oct 08, 2021 11:02 pm
Location: Dorset, UK
Has thanked: 93 times
Been thanked: 179 times

Drive mode selector using Arduino

Post by catphish »

Hi,

I wrote a quick Arduino program today to accept switch inuts and dyamically reconfigure openinverter to choose from different drive profiles like "Eco", "Normal", "Sport". This requires an Arduino with a CAN shield, and a CAN connection to the inverter.

It's pretty simple, but I thought I'd share it here in case it's of use to others. Essentially it just de-rates the maximum throttle (and for off-road mode it cranks up the regen). It's easily modified to control other parameters, you just need to look up the persistent IDs for them here: https://github.com/jsphuebner/stm32-sin ... _prj.h#L30

Code: Select all

#include <CAN.h>
#include <Metro.h>

#define MODE_NORMAL 0
#define MODE_SPORT 1
#define MODE_ECO 2
#define MODE_OFFROAD 3

#define INPUT_SPORT 0
#define INPUT_OFFROAD 1
#define INPUT_ECO 3
#define RED_SPORT 4
#define RED_OFFROAD 5
#define RED_ECO 6
#define BLUE_SPORT 7
#define BLUE_OFFROAD 8
#define BLUE_ECO 10

void setup() {
  CAN.begin(500000);

  pinMode(INPUT_SPORT, INPUT_PULLUP);
  pinMode(INPUT_OFFROAD, INPUT_PULLUP);
  pinMode(INPUT_ECO, INPUT_PULLUP);
  
  pinMode(RED_SPORT, OUTPUT);
  pinMode(RED_OFFROAD, OUTPUT);
  pinMode(RED_ECO, OUTPUT);
  pinMode(BLUE_SPORT, OUTPUT);
  pinMode(BLUE_OFFROAD, OUTPUT);
  pinMode(BLUE_ECO, OUTPUT);
}

void set_parameter(uint8_t parameter, int32_t value) {
  value = value * 32;
  CAN.beginPacket(0x601); // SDO
  CAN.write(0x40);        // Set
  CAN.write(0x01);        // Parameter by ID
  CAN.write(0x20);        // Parameter by ID
  CAN.write(parameter);   // Parameter ID
  CAN.write(value >> 0);
  CAN.write(value >> 8);
  CAN.write(value >> 16);
  CAN.write(value >> 24);
  CAN.endPacket();
}

void set_throtmax(int32_t value) {
  set_parameter(97, value);
}

void set_brkmax(int32_t value) {
  set_parameter(49, value);
}

Metro can_timer = Metro(500);

void loop() {
  int mode = MODE_NORMAL;
  if(!digitalRead(INPUT_SPORT)) mode = MODE_SPORT;
  if(!digitalRead(INPUT_OFFROAD)) mode = MODE_OFFROAD;
  if(!digitalRead(INPUT_ECO)) mode = MODE_ECO;

  digitalWrite(RED_SPORT, mode == MODE_SPORT);
  digitalWrite(RED_ECO, mode == MODE_ECO);
  digitalWrite(RED_OFFROAD, mode == MODE_OFFROAD);

  digitalWrite(BLUE_SPORT, mode != MODE_SPORT);
  digitalWrite(BLUE_ECO, mode != MODE_ECO);
  digitalWrite(BLUE_OFFROAD, mode != MODE_OFFROAD);

  if (can_timer.check()) {
    if(mode == MODE_SPORT) {
      set_throtmax(100);
      set_brkmax(-20);
    } else if(mode == MODE_ECO) {
      set_throtmax(55);
      set_brkmax(-30);
    } else if(mode == MODE_OFFROAD) {
      set_throtmax(75);
      set_brkmax(-75);
    } else { // MODE_NORMAL
      set_throtmax(75);
      set_brkmax(-30);
    }
  }

}
User avatar
joromy
Posts: 371
Joined: Fri Jun 28, 2019 12:56 pm
Has thanked: 1 time
Been thanked: 3 times

Re: Drive mode selector using Arduino

Post by joromy »

Thank you for sharing, have been looking for something like this. I alredy have a Teensy as my main ECU/display.
Simple is good ;)
Thomas A. Edison “I have not failed. I've just found 10,000 ways that won't work"
nkiernan
Posts: 505
Joined: Mon Feb 24, 2020 8:59 pm
Location: Ireland
Has thanked: 276 times
Been thanked: 64 times

Re: Drive mode selector using Arduino

Post by nkiernan »

Cheers Catphish :)
Post Reply