Hi all,
I pimped up a bit the source code to have some more functionalities :
- Scooter keeps turned on.
- Light can be turned on and off by adding a toggle switch to the arduino (press switch can be easily implemented).
- Scooter is locked and wheels blocked when power is cut on arduino. The code will detect input power going down and will send lock code before dying. Really handy !
How to cable it :
- Red and black wire from scooter goes to step down buck converter. Add a simple toggle switch on the 42v+ line to be able to cut power to the Arduino.
- Add another toggle switch between 5v on Arduino to A0.
- Connect RX and TX as explained before.
- Connect blue cable to the D2 on Arduino.
Everything has been tested (I don't know the model), speed is very good and acceleration also ! Will try on other models if possible.
Evolutions :
- More fluid startup, for now the scooter try hardly to start and succeed after some times
- Unlock speed (need somebody to find the hex code to send
- Boost acceleration (if possible ?)
- Bluetooth lock / unlock
- Any idea ?
Here is the source code, explained so everybody can add or modify code easily :
Please share !
Code: Select all#include <Arduino.h>
// ------------------------------------------------------------------------------------------- SETTINGS
// Digital output which send voltage to the brain
int powerPin = 2;
// Analog pin where is connected the light switch
int lightSwitchPin = 0;
// Threshold to detect shutdown and send lock command before turning off (in mV)
int vinShutdownVoltage = 3600;
// Voltage to consider a switch on for the light (in V)
int lightOnVoltage = 2;
// ------------------------------------------------------------------------------------------- HELPERS
/**
* Read VIN voltage
*/
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}
/**
* Quick blink of the internal LED
*/
void blink ()
{
for (int i = 0; i < 8; i ++)
{
delay( 40 );
digitalWrite(LED_BUILTIN, (i % 2 == 0) ? HIGH : LOW);
}
}
// ------------------------------------------------------------------------------------------- COMMANDS
// Commands sent to the brain
void sendStartCommand ()
{
byte command[] = {0xA6, 0x12, 0x02, 0x11, 0x14, 0x0B};
Serial.write( command , sizeof(command) );
}
void sendLightCommand ()
{
byte command[] = {0xA6, 0x12, 0x02, 0x15, 0x14, 0x30};
Serial.write( command , sizeof(command) );
}
void sendStopCommand ()
{
byte command[] = {0xA6, 0x12, 0x02, 0x10, 0x14, 0xCF};
Serial.write( command , sizeof(command) );
}
// ------------------------------------------------------------------------------------------- SETUP LIFECYCLE
// Counter for each loop to send commands with smaller delays
int stepCounter = -1;
// Counter to allow shutdown only after everything is up
int allowShutdownCounter = 0;
// Light state (true is on)
bool lightState = false;
void setup()
{
// We speak serial with the brain
Serial.begin( 9600 );
// Configure IO
pinMode( LED_BUILTIN, OUTPUT );
// Enable digital pin to talk to the brain
pinMode(powerPin, OUTPUT);
digitalWrite(powerPin, HIGH);
// Start
sendStartCommand();
delay(100);
blink();
}
// ------------------------------------------------------------------------------------------- LOOP LIFECYCLE
void loop ()
{
// --- Light state and repeat to keep alive
// Counter to allow faster turn off state
stepCounter ++;
// Read analog value for light switch
int lightLevel = analogRead( lightSwitchPin );
float lightVoltage = lightLevel * (5.0 / 1024.0);
// Convert voltage to boolean, is light switch on ?
bool newLightState = ( lightVoltage > lightOnVoltage );
// If light switch state is different than light state
// Or if we elapsed some time
if (
// This is to avoid flooding and only send when state changes
( newLightState != lightState && stepCounter >= 50 )
// This is because we need to send last command to avoid the brain to sleep
|| stepCounter >= 500
// First init of light state
|| stepCounter == -1
) {
// Reset step counter and update light state
stepCounter = 0;
lightState = newLightState;
// If voltage is near 5V, turn on light and start the engine
lightState ? sendLightCommand()
// Otherwise, just start the engine and keep it on
: sendStartCommand();
}
// --- Shutdown detection
// Set a counter to allow shutdown. This is to avoid shutdown detection at startup
if ( allowShutdownCounter < 200 ) allowShutdownCounter ++;
// Read VIN value and if voltage is droping
while ( readVcc() < vinShutdownVoltage && allowShutdownCounter >= 200 )
{
// We tell the brain to stop
sendStopCommand();
digitalWrite(powerPin, LOW);
// Blink until death
while (true) blink();
}
// --- Repeat
// Wait a bit to avoid flooding the brain
// With this low delay we can detect voltage drop in VIN and lock before we turned off
// +2ms in readVcc()
delay( 3 ); // 5ms
}