Sunday, 7 January 2018

LunchBox ESkateboard Part 3 : Arduino Software


Unlike radio receiver, Arduino needs to be programmed manually to output correct PWM signal to ESC. The skateboard ESC I used expected to receive pulse every 20ms (50Hz) and the minimum time of the pulse is 1ms while the maximum is 2ms. (This is the standard PWM signal for controlling servo). Because I configured the ESC mode to be forward with brakes, a signal with duty cycle above 50% (1.5ms~2ms) will rotate the motor forward while a signal with duty cycle below 50% (1ms~1.5ms) will trigger the brake. If ESC receives a signal with duty cycle 50%, it will not output any command to motor and therefore allowing it to rotate freely. 

Luckily, Arduino has a ready-to-use servo library for outputting the desired PWM signal. So in my code I initialized servo with minimum and maximum as required by the PWM signal. 
#include <Servo.h>

Servo mServo;
const int minPulseRate = 1000;
const int maxPulseRate = 2000;
mServo.attach(pwmPin, minPulseRate, maxPulseRate);

After the above initialization, one can use mServo.write API to send a PWM signal with desired pulse width. For example, mServo.write(1500) will send a PWM signal with pulse width 1.5ms.
The value sent from smartphone was an integer from 0-100. For me, I wanted to control the speed precisely with a multitude of speed levels while it asw not very important for me to control the brake strength precisely. Therefore, I chose to control the skateboard in following way:
1. Neutral speed corresponds to integer value 10. If smartphone sends an integer 10, the Arduino 101 will output a PWM of duty cycle 50% (pulse width 1.5ms)
2. Values from 10-100 are forward speed commands. The values will be linearly mapped to pulse width 1.5ms(1500us) to 2ms(2000us)
3.  Values from 0-10 are brake strength, with 0 being the strongest brake. The values will again be linearly mapped to pulse width 1ms(1000us) to 1.5ms(1500us)

The code is presented below:
void switchCharacteristicWritten(BLEDevice central, BLECharacteristic characteristic) {
  // central wrote new value to characteristic, update LED
  // Serial.print("Characteristic event, written: ");
  int pwmVal;
  if (switchChar.value() >= neutralSpeed) {
    // map from 10-100(0-90) to 1500-1950
    pwmVal = ((switchChar.value() - neutralSpeed) * 5) + 1500;
  } else {
    // map from 0-10(-10-0) to 1000-1500
    pwmVal = ((switchChar.value() - neutralSpeed) * 50) + 1500;
  }
  // Serial.println(pwmVal);
  mServo.write(pwmVal);
}
With the above code, Arduino 101 could interpret the value sent from smartphone and send PWM command to ESC. For bluetooth communication, since Arduino101 has a ready-to-use bluetooth library, one can refer to official tutorial or simply refer to my full code at Github.

I also programmed an onboard LED to reflect the state of Bluetooth communication. Simply if Bluetooth connection is not established, the LED will blink with 500ms interval whereas if Bluetooth connection is established, the LED will stay on.

No comments:

Post a Comment