Arduino sketch to control and read ASI BAC Controller

Electric Motors and Controllers
Post Reply
ProEV   100 mW

100 mW
Posts: 47
Joined: Aug 22 2013 9:56am

Arduino sketch to control and read ASI BAC Controller

Post by ProEV » Jun 29 2019 10:18am

Hi,

Here is a basic demo sketch to use the Modbus protocol to read motor temperature, RPM, voltage and current from a ASI BAC controller and write to the controller to change the percentage of full power available. This is tested using a Ardunio Mega 2560 and a ASI BAC2000. I have not tested it with ebikes.ca great Phaserunner but it is an ASI based product.

I write sloppy code and am happy to hear any suggestions for improvements.

Cliff
www.ProEV.com

/*
This is an demo program for controlling and reading an ASI BAC Controller with an Arduino.
It has been tested with a ASI BAC 2000 controller and a Mega 2560.

You need to download SimpleModbusMaster library

This version allows the the user to set the Percentage of full power available.
It reads Motor Temperature, Motor RPM, Battery Voltage, Current.

The program starts reading at parameter 261 and reads the next 5. These are stored in the array 'reg'
Many other parameters could be read, but these were what I needed. ASI lists parameters on their website.

The program gets a value from Array postion 6 and writes it to Parameter 155

The basic inelegant error checking looks for gross errors in the numbers returned and any exception code.
It does not use the Cyclic Redundany Check which would catch all errors. Anyone who wants to write this?

Created by ProEV
This example code is in the public domain.
*/

#include <SimpleModbusMaster.h>

#define TxEnablePin 2 // RS485 modbus direction control pin:
#define baud 115200 // modbus port speed:BAC manual says 115200
#define timeout 100 // modbus timeout in mSec:tried 100 from 1000
#define polling 10 // modbus scan rate in mSec:tried 50 from 100
#define retry_count 15

#define TOTAL_NO_OF_REGISTERS 7// number of registers to poll

enum
{
PACKET1,
PACKET2,
TOTAL_NO_OF_PACKETS // leave this last entry
};

Packet packets[TOTAL_NO_OF_PACKETS]; // array of Packets to be configured

//packetPointer packet1 = &packets[PACKET1];

int regs[TOTAL_NO_OF_REGISTERS]; // master register array

//set up variables

long RPM = 0;
double volts = 0;
double amps = 0;
double motort = 0;

int errors = 0;//for setting number of errors before reboot
int reboots = 0;//for tracking reboots of modbus

void setup()
{
// initialize both serial ports:
Serial.begin(9600);
Serial1.begin(115200);//wire controller serial wires to serial1 connection

modbusboot(); //boot Modbus for this readings

}

void loop()
{

Serial.print("Setting before modbus update: ");
Serial.println(regs[6]);

regs[6] = 4096;//Change this number to set Percentage of Full Power. 4096 is 100%, 2048 is 50% power

modbus_update();

Serial.print("Reset power to after modbus update: ");//the first time the request is succeful, this value will change to your value
Serial.println(regs[6]);

Serial.print("Exception errors: ");
Serial.println(packets[PACKET1].exception_errors);

Serial.print("Failed requests: ");
Serial.println(packets[PACKET1].failed_requests);

Serial.print("Successful requests: ");
Serial.println(packets[PACKET1].successful_requests);

Serial.print("Motort raw: ");//parameter 261 from controller
Serial.println(regs[0]);


//if failed request try reboot modbus
//If out of probable range, reboot Modbus
if (packets[PACKET1].failed_requests > errors
|| (packets[PACKET1].exception_errors)> 0
|| regs[2] > 20000
|| regs[2] < -1000
|| regs[4] > 3200
|| regs[4] < 0
|| regs[5] > 4160
|| regs[5] < -4160)

{
modbusboot();
modbus_update();
Serial.println("Reboot ");
errors += 1; //increment count of failed requests
reboots += 1; //increment count of reboots
}
else {
motort = regs[0];//parameter 261
motort *= 9;
motort /= 5;
motort += 32;//to Fahrenheit

RPM = regs[2];//parameter 263

volts = regs[4];//parameter 265
volts /= 32;

amps = regs[5];//parameter 266
amps /= 32;
}
Serial.print("MotorTemperature: ");//parameter 261 from controller
Serial.println(motort);
Serial.print("RPM: ");
Serial.println(RPM);
Serial.print("Battery Voltage: ");
Serial.println(volts,3);
Serial.print("Battery Current: ");
Serial.println(amps,3);
Serial.print("Current% ");
Serial.println(regs[6]);
Serial.print("reboots ");
Serial.println(reboots);
Serial.println("----------");
}


void modbusboot()//intializes modbus

{
modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 261, 6, 0); /*1 works, 2 works but not 3
initialize packet 1, slave 1, Function 3, address to read from Motor temperature 261,RPM 263, bat voltage is 265, amps is 266),
number of registries to read +1 spare or last does not read correctly if reading or data to write if function 6
to read, the last is index of address map?
*/

modbus_construct(&packets[PACKET2], 1, PRESET_MULTIPLE_REGISTERS, 155, 1, 6); /*
initialize packet 1, slave 1, Function 16, address to write to 155 for battery current % must divide by 40.96,number of registries to write if function 16
to read, the last is reading from the array reg[6] to get data to write.
*/
modbus_configure(&Serial1, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs); //8N1 not standard but should work

Serial.println("reboot modbus");
reboots+=1;

}

guiga   10 µW

10 µW
Posts: 6
Joined: May 27 2018 11:54am

Re: Arduino sketch to control and read ASI BAC Controller

Post by guiga » Aug 07 2019 4:45am

thanks for sharing this sketch, i will give a try as soon i can

Post Reply