An Electric Scooter Community on a Mission to Stamp out Transportation Mediocrity.

Changing mobility one trip at a time.
#19584
Cheedo wrote:
Fri Jan 24, 2020 1:10 pm
Zou wrote:
Mon Dec 16, 2019 1:59 pm
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
}
hey Zou, this is amazing! thank you! i took your code and created my own using your commands, link below. i have yet to fully test the code yet so use at your own risk. i found two commands that give me 20MPH with me 200B with light on and with light off. worst case just steal those commands :)

my code is setup right now so D2 on the nano is the light switch (5V = on, 0V = off), and i borrowed your genius method of reading the 5V supply to send the shutdown command (supply is read on A0). i will be testing this tomorrow once my buck converters come in and will post an update.

code:
https://create.arduino.cc/editor/Cheedo ... f2/preview

Buck Converter I use:
https://www.amazon.com/gp/product/B016V ... UTF8&psc=1

hope this helps somebody!
Hello, it is not clear to me how to wire it you could clarify yellow and green, it does not work for me. Thank you
#19682
Any news on the es200g sequence needed to prevent the esc to shutdown after 2 minutes? Would be nice to have a dump of the original communication for the first minutes... Anyone willing to share this raw info? That's all we need to solve the puzzle and I am sure its solved fast if the dump is shared... if no-one going to post I will do a recording of the communication in the next days...
#19686
It's not that simple anymore...
Seems like the ESC now sends a signal to the IoT (or if it was the other way around), and expects a response calculated by an unknown algorithm. If the correct reply is not received the ESC goes to lockdown.
The reply is no longer the same, it changes all the time.

So it's no longer enough to just capture the signals and replicate them, you would have to figure out the algorithm used to calculate the correct response message.
solarwasser wrote:
Thu Feb 13, 2020 9:38 pm
Any news on the es200g sequence needed to prevent the esc to shutdown after 2 minutes? Would be nice to have a dump of the original communication for the first minutes... Anyone willing to share this raw info? That's all we need to solve the puzzle and I am sure its solved fast if the dump is shared... if no-one going to post I will do a recording of the communication in the next days...
#19697
My prediction is that the algorithm could be based off the running time of the scooter (and maybe it's serial number?) Unless the ESC has access to on board memory, I predict it may expect the same sequence of codes each time the enable pin goes high and the scooter turns on. If the sequence is the same each time the scooter gets up and running, maybe you could capture the first 20 minutes or so of responses? To keep it alive for longer? Not sure if it works this way but it would definitely be worth capturing packets when the scooter turns on, and running a recapture to see if anything changes on the second boot
UgloBuglo wrote:
Fri Feb 14, 2020 5:35 am
It's not that simple anymore...
Seems like the ESC now sends a signal to the IoT (or if it was the other way around), and expects a response calculated by an unknown algorithm. If the correct reply is not received the ESC goes to lockdown.
The reply is no longer the same, it changes all the time.

So it's no longer enough to just capture the signals and replicate them, you would have to figure out the algorithm used to calculate the correct response message.
solarwasser wrote:
Thu Feb 13, 2020 9:38 pm
Any news on the es200g sequence needed to prevent the esc to shutdown after 2 minutes? Would be nice to have a dump of the original communication for the first minutes... Anyone willing to share this raw info? That's all we need to solve the puzzle and I am sure its solved fast if the dump is shared... if no-one going to post I will do a recording of the communication in the next days...
#19709
This week I might be able to sacrifice some time in the evenings to move my laboratory RV to the next city because it seems VOI created a new area here.....so I don't need to drive a few hundred miles to test anything like sniffing signals or test the next stage of my LORA pirate board solution. So i can get you a record of the communication.
By the way, how do you guys deal with the situation in countries that force insurance and licence plate for those scooters like Germany or Netherlands do? At the *Buuuuurrrrbbb*moment it doesn't affect me I just ride my MyTier redesigned ES200 and the country I'm actually in equaled them basically to bikes. But there might be a chance they send me over to Germany for a few months for education and I'm thinking about saving some nice $¥£€ by getting my camping trailer there and riding to the company with my scooter instead of getting a hotel or apartment there. (German rental costs for apartments are crazy and my company would pay me by a rise :roll: ) Since we don't have the papers for the scooters it could be a little tricky to get them insured and licensed there :?
#19715
https://pastebin.com/4Ckwhzji

I've attached a dump of some new scooter data. This is the data that the scooter receives from the IOT box for activation. You can see that the same old 6a 12 02... activation command is still the same, but the new expected command starts with 7a 12 0a... and then has a series of 11 bytes that are calculated through the algorithm. The dump was a random 3 minute capture from a scooter that was activated (glitched) for a few days.
https://gyazo.com/b637361f75a1f96671e1a1966ddd1566
This view in notepad visualizes the data a bit better. I have a bird that is running the new software with the new security bytes, but is in a glitch state and has been activated for about 5 days now running at full speed. If theirs any sort of debugging tips I can do to maybe help track down how the algorithm is calculated, definitely let me know. In theory the scooter will be on until it loses power, so as long as I keep it charged I should have enough time to crack the code, as long as I know what im looking for.
  • 1
  • 61
  • 62
  • 63
  • 64
  • 65
  • 80

As this was a rental version whos overstock was […]

Any one got any info on beryl bikes I seen a few[…]

LH/ TF-100 Style Display.

Hi I recently converted a Bird Zero to a personal […]

How do you operate dash without button? I have[…]