Arduino VESC Remote

Forum dedicated to electrical projects
User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Fri Jul 01, 2016 2:39 pm

I began working on some code for testing purposes. I made a little program to measure the hall effect sensor and battery and display info about them on the screen.
Here is a video of the remote running the test program:

youtu.be/1jJkVAt6YOw

Most of the code is modified from examples I found online. I also included a very basic calibration routine which I will be working on more later for the final remote. Here is the code:

Code: Select all

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// If using software SPI (the default case):
#define OLED_MOSI   6
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

#define XRANGE  19

int x,gss,y;

const int sensorPin = A0;

int sensorValue = 0;         // the sensor value
int sensorMin = 700;        // minimum sensor value
int sensorMax = 200;           // maximum sensor value


void setup()   {               
  Serial.begin(9600);
 
  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC);
  // init done
 
  // Show image buffer on the display hardware.
  // Since the buffer is intialized with an Adafruit splashscreen
  // internally, this will display the splashscreen.
  display.display();
  delay(2000);

  // Clear the buffer.

  display.clearDisplay();

  while (millis() < 10000) {
    sensorValue = analogRead(sensorPin);
 
    // record the maximum sensor value
    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
    }
 
    // record the minimum sensor value
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
    }
  }
}


void loop() {

  #define VBATPIN A7
   
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2;    // we divided by 2, so multiply back
measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage

int percent;
const float lipoDc[2][11] = { { 3.2, 3.680,3.740,3.780,3.810,3.850,3.870,3.960,4.02,4.100,4.200 } ,{ 0.000, 0.100,0.200,0.300,0.400,0.500,0.600,0.700,0.800,0.900,1.000 } };
int ind;
  if(measuredvbat>=4.2)
    percent=100;
  else
  {
    while (!(measuredvbat<=lipoDc[0][ind+1] && measuredvbat > lipoDc[0][ind])&& ind<=10)
    {
      ind++;
    }
 

    if (measuredvbat <= lipoDc[0][ind + 1] && measuredvbat > lipoDc[0][ind])
    {
      float CapacPers = (((lipoDc[1][ind + 1] - lipoDc[1][ind])/ (lipoDc[0][ind + 1] - lipoDc[0][ind]))*(measuredvbat - lipoDc[0][ind])) + lipoDc[1][ind];
    //  int intCapacPers = (int)(CapacPers * 100);
      percent = (int)(CapacPers*100.0);
    }
  }

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(48,0);
  display.clearDisplay();
  display.print(percent);
  //display.print(measuredvbat);
  display.println("%");

  display.setCursor(0,30);
  display.setTextSize(1);
 
   
  int aValue =analogRead(0);
 
  y = map(aValue, sensorMax, sensorMin, 0, 1024);

  if (y < 552 && y > 472)
    y = 512;

  x = map(y, 0, 1024, 0, XRANGE);


 
  display.print("|");
  for (int i=0;i<x;i++){
    if(i==XRANGE/2)display.print("|");
    else display.print("-");
  }
  display.print("O");
  for (int i=x+1;i<XRANGE;i++){
    if(i==XRANGE/2)display.print("|");
    else display.print("-");
  }
  display.print("|");

  display.setCursor(53,50);
  display.print(y);

 display.display();
 
}



So lets break up the code and explain what's going on.

Hall Effect Calibration
Starting off, in the setup, there are a few initiations for the display and serial but the main thing is the calibration bit:

Code: Select all

while (millis() < 10000) {
    sensorValue = analogRead(sensorPin);
 
    // record the maximum sensor value
    if (sensorValue > sensorMax) {
      sensorMax = sensorValue;
    }
 
    // record the minimum sensor value
    if (sensorValue < sensorMin) {
      sensorMin = sensorValue;
    }

After to two second screen splash, this bit of code looks at the min and max value from the hall effect sensor. In the video, you will see me rest the remote and push the thumb leaver to full throttle and full brake. This is so this bit of code can adjust the absolute min and max of the control. This information is used later in the program, and we will revisit this later.

Reading the Battery
So adafruit did a nice job with their battery system on the feather. Not only is there a charging system, but they actually have a built in voltage divider tied to pin 9 from the battery. This means you can read that pin to get the battery voltage. Here is the code I used to do just that:

Code: Select all

#define VBATPIN A7
   
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2;    // we divided by 2, so multiply back
measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage


Correlating Voltage to Capacity
I wanted to know the percentage of the battery, not its voltage. Although it is not extremely accurate, you can match a given voltage of the battery to a percentage of capacity. Using an array to do this, you can also have some estimation between point values. See the code here:

Code: Select all

int percent;
const float lipoDc[2][11] = { { 3.2, 3.680,3.740,3.780,3.810,3.850,3.870,3.960,4.02,4.100,4.200 } ,{ 0.000, 0.100,0.200,0.300,0.400,0.500,0.600,0.700,0.800,0.900,1.000 } };
int ind;
  if(measuredvbat>=4.2)
    percent=100;
  else
  {
    while (!(measuredvbat<=lipoDc[0][ind+1] && measuredvbat > lipoDc[0][ind])&& ind<=10)
    {
      ind++;
    }
 

    if (measuredvbat <= lipoDc[0][ind + 1] && measuredvbat > lipoDc[0][ind])
    {
      float CapacPers = (((lipoDc[1][ind + 1] - lipoDc[1][ind])/ (lipoDc[0][ind + 1] - lipoDc[0][ind]))*(measuredvbat - lipoDc[0][ind])) + lipoDc[1][ind];
    //  int intCapacPers = (int)(CapacPers * 100);
      percent = (int)(CapacPers*100.0);
    }
  }


We can now print this info out to the display using this code:

Code: Select all

display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(48,0);
  display.clearDisplay();
  display.print(percent);
  //display.print(measuredvbat);
  display.println("%");


Remapping and Visualizing Hall Effect
Now revisiting the hall effect code from earlier, we need to remap it to a standard range. In this case I decided to map it to 1024 to be used later for throttle control. I also gave a 40 unit margin around the middle point. If it is plus or minus 40 from 512, it returns as 512. I also wanted a way to visualize the readings. I did another map from our new 1024 map but this time I mapped it to XRANGE which was defined as 19. This was the largest value I could find that would fit the full width of the OLED display. This new map info is used to print a visualizing bar. I also decided to print out y (the current value in our 1024 range) for reference.

Code: Select all

  int aValue =analogRead(0);
 
  y = map(aValue, sensorMax, sensorMin, 0, 1024);

  if (y < 552 && y > 472)
    y = 512;

  x = map(y, 0, 1024, 0, XRANGE);


 
  display.print("|");
  for (int i=0;i<x;i++){
    if(i==XRANGE/2)display.print("|");
    else display.print("-");
  }
  display.print("O");
  for (int i=x+1;i<XRANGE;i++){
    if(i==XRANGE/2)display.print("|");
    else display.print("-");
  }
  display.print("|");

  display.setCursor(53,50);
  display.print(y);

 display.display();


Well that's it for now, I will continue fiddling with code and hopefully I can get a nice calibration program written in a timely manner. On a side note, I ordered another set of arduino parts so I can have one remote for development and one for hardware testing, ie durability testing.

Updates to come!
Science may set limits to knowledge, but should not set limits to imagination.

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Sun Jul 24, 2016 2:03 am

Since the last update, a few things have happened. I continued tweaking the remote housing so it feels better in the hand. The most notable change was its thickness was increased by 4mm for a total of about 19mm. The external and internal chamfers were adjusted for both a better feel and added strength. Other minor changes included updated screw posts with reinforced bottoms, adjusted Hall effect sensor placement, and updated throttle spring plate. As far as the housing goes, it is well.

Unfortunately, it has been brought to my attention that the BLE module does not support central mode (a master connection type) and thus can only be used as a peripheral device. This is a huge problem as that is what we need it to use. It turns out that Adafruit loads their own firmware on the Bluetooth and the firmware is the limiter In this case.

More research is needed and I have since attempted to contact Adafruit to ask them for a firmware update. I will most likely have to use a different Bluetooth module or flash it myself if I am to continue.

Updates to come.
Science may set limits to knowledge, but should not set limits to imagination.

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Tue Aug 30, 2016 10:54 pm

After about a month of research and collaboration, I have excellent news!
I have been working with someone on the feather BLE module and we have successfully flashed and tested firmware with central mode functionality!!! :D :D :D We used an existing stack (heartbeat) used for fitness devices and was able to communicate with a usb bluetooth module which was configured as a peripheral device. This proves the feather can work for what we need!!!

The next step will be to load a UART stack and play with that. I will have more details as progress is made.

Updates to come!
Science may set limits to knowledge, but should not set limits to imagination.

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Thu Oct 13, 2016 9:45 am

Ok so a lot has happened recently. I had to put the project on hold for a little bit to catch up on some other work but I am now back to working on this. I have done a fair amount of work over the last two days.

Firstly, I rewired the OLED display from SPI to I2C to conserve digital pins. While I had it open, I also wired up the FRAM module via I2C and the trigger button. At this point, the only things left to wire are the two front buttons which I will get to today.
I adjusted my code for the new display and tested out the memory and trigger button. I also made a nice little case to hold the remote and extra parts and I wrote an outline for the remote functions, menu system and features.
Some pictures:
image.jpeg
image.jpeg
image.jpeg


The main thing I need to work out (other than the ble) is power management. I.e. How to turn it on and off. There are essentially two ways to do this with this board. Add an external switch or circuit to tie the EN pin to ground to shut off the 3.3v rail, or implement low power mode/sleep mode to all power consuming components with an interrupt routine to wake.
The first rout would be easiest, all that would be required is a small toggle switch, however this poses two issues in my mind. One, there is a major safety concern with a mechanical switch as it could accidentally be switched off when riding. Second, it takes up extra space and would make the remote slightly less elegant. Alternatively, a latching circuit with logic input from the feather could be used to solve this, but that would add expense and require internal space which is running very low. (This would not be an issue later with a pcb)
So for now, I am going to go with the second option and see how low I can get the power draw. I have started by adding code to turn off the display after 20 seconds. Just this resulted in a battery drop from 2-3 percent/hour to around 1 percent per hour. Putting the ble module and main cpu in a low power state or sleep state could reduce this battery drain to less than a percent every 12 hours. If I can get it to this point, that will be acceptable for the final design. However, if not, I will revisit the first option with the latching circuit and implement that later when it is pcb'd.

So in conclusion, I will be working on the ble, power management, and code until the next update.
Science may set limits to knowledge, but should not set limits to imagination.

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Sat Dec 31, 2016 7:46 pm

Since the last update, I have done a lot of code work. The remote now has a fully functioning menu system that is object based. I had to get a lot of help to learn how to do this as the original method I was using (array) was getting very messy. I have also made a few minor revisions to the housing and printed it in black. It looks very good in black! :D
1.jpg

3.jpg

4.jpg


There are a few things I am sorting out before moving to the BLE when I get back from break. Firstly, the tactile switches I got from amazon seem to be low quality and don't always remain activated even when clicked. This presents a safety concern especially with the trigger button as it will cut the throttle if not pressed (or not pressed hard enough). I have looked at a few different types I had laying around the house and they all don't seem to have this issue. I have just placed an order from Mouser for a few different types of switches from Panasonic with low actuation force so I will spend some time trying these different ones.
Another thing I want to do is rewire the display and buttons. The display is currently running over I2C and it has a fair bit of latency compared to SPI. I have it in I2C to conserve digital pins for the buttons, but I forgot I can do a digital read from the analog pins as well. :roll:
The last thing I want to work out is the font for the menu and main display screen. Right now I am using the default font from the GFX library and it's fine but when you want to make it bigger, the only way is to scale it and it looks very low res and blocky. There are other fonts but whenever I call them, they are much bigger than I would like (even the 9pt). I have played with it for hours and looked it up with no avail. I will have to make a post about it on the Adafruit forums to get it sorted out. :?

Anyway, as usual, updates to come!
Cheers!
Science may set limits to knowledge, but should not set limits to imagination.

bolterican
Posts: 0
Joined: Thu Jan 05, 2017 8:41 pm

Re: Arduino VESC Remote

Postby bolterican » Thu Jan 05, 2017 9:04 pm

It's a really cool job.

I am also making a remote contoller, but the design of my remote is not very good.

If you do not mind, can I get the STL file from your remote?

My email is [email protected].

Thank you.
Attachments
P20151228_101552680_F185E4DC-01DB-49F0-8361-20D0404B3163.JPG

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Thu Jan 05, 2017 9:47 pm

Hello bolterican,
I will send the current files over to you via direct message so you can test them out. I still have a few revisions before I release them along with the schematic and code so stay tuned for updates.
Cheers!
Science may set limits to knowledge, but should not set limits to imagination.

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Thu Jan 12, 2017 12:10 pm

My new tact switches came in and wow are these sensitive! When I first installed them in the remote, I didn't think it was clicking at all. I guess 1N of force is not a lot. Anyway, these may be a bit too soft so I will order some 2N and some 3N ones to play with. Also, these new switches have the same problem as the old with them not activating even when clicked if not enough pressure is applied. Since this is the case, I have thought of a way to implement a spring-like cantilever into the trigger part itself such that when held down, it will apply a constant pressure to the switch even if there is noise in the pressure applied to the trigger itself. This also will also give the trigger a longer throw and will ensure the switch is activated within a larger pressed down range of the trigger. I will begin the redesign of this part today and should have a working prototype within the next few days.

I also rewired the display to SPI and wasted a few hours troubleshooting it to realized that I forgot to desolder the two bridged pads on the back of the display that enables I2C. I am however having some errors in my code that I will have to sort out before continuing with it.

Anyway, updates to come!
Science may set limits to knowledge, but should not set limits to imagination.

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Fri Jan 13, 2017 9:19 pm

Well, things moved a bit faster than I anticipated. I was able to print my trigger prototype and increment through a few revisions very quickly since the build time for it was only 10 minutes. I ended up having 4 revisions to get the print uniform and the feeling satisfactory. Here are some pictures of the revisions and a video comparing the old trigger to the new one:
IMG_7835.jpg



youtu.be/RSL3s4L68RA

I am very happy with how this feels and how well it works. This has been a concern for quite a while so I am glad to see it resolved. I still feel that the switch requires a bit too much force to activate. I'm guessing it is a 6 or 7 Newton activation. I will be finding and ordering some new switches in the same form factor with 2N, 3N, 4N, and 5N activation forces. I think the 3N will be best but I will try all to see.

As usual, updates to come!
Science may set limits to knowledge, but should not set limits to imagination.

User avatar
Josh Hess
Site Admin
Posts: 129
Joined: Sun May 24, 2015 6:00 pm
Location: Orlando, FL
Areas of Knowledge: Electronics, Product Design, Manufacturing
School/University: UCF

Re: Arduino VESC Remote

Postby Josh Hess » Sat Mar 18, 2017 3:47 pm

An update on the BLE module. Although I was successful in flashing a different firmware on it that supported central mode, this module is proving to be very difficult to use as a serial passthrough. I have started looking at other options and have decided to move away from arduino all together and to just design and PCB my own board with a better module. Unfortunately, this means I won't be releasing the code I wrote for the arduino. I would say it is still possible to use the Adafruit feather m0, but with an nRF module with RollingGecko's code. However, this presents other potential safety issues, so I won't be pursuing this at all and will be moving forward with my custom BLE-based solution.
Science may set limits to knowledge, but should not set limits to imagination.


Return to “Electrical”

Who is online

Users browsing this forum: No registered users and 2 guests