How to send randomly generated values to BLDC via FOCBOX

definitely not a nuisance! this is a very interesting topic AND it’s for the greater good. no need to go anywhere :slight_smile:

Thanks GrecoMan!

1 Like

Just to make sure the image everyone is getting of the set up is correct I am using the motor as a friction drive for the 27” inch wheel.

1 Like

I love how you can meet so many people with different skills in this community, neuroscience completely black magic for me :smiley:

Just a small summary for the Arduino way of doing this. You would need to send the random values via serial communication to the arduino, which in turn requires the app Processing as a middle man between your numbers and the arduino. Then the arduino would either send a PWM Signal to the VESC in Duty Cycle Mode or send the actual RPM Value via serial communication to the VESC. (latter would probably give more resolution). This would require an Arduino Mega for best serial performance.

This of course is the quick and dirty, and probably less reliable, way to do this. But it’s easy because there is no additional hardware and software required and it doesn’t require programming on any VESC related things, so it might be good for a proof of concept.

Another idea would be to use a USB to UART adaptor (or FTDI Stick), so you could directly send serial data to the VESC from you computers USB Port. But i am not sure how to get a sort of VESC Library for this method.

For some Arduino sample this might work but I have not tested it and it is only a theory. No guarantee that it works - use it at your own risk.

// VESC PWM Signal connected to this pin (can be another PIN - make sure to adjust this for the Arduino you are using) - don't forget to connect GND as well

int VescPin = 9; 



void setup() {

  // put your setup code here, to run once:

  Serial.begin(9600);

  // sets the pin as output

  pinMode(VescPin, OUTPUT);   

}



void loop() 

{

  // Read serial input:

  while (Serial.available() > 0) {

	int inChar = Serial.read();

	if (isDigit(inChar)) {

	  // convert the incoming byte to a char and add it to the string

	  inString += (char)inChar;

	}

	

	// if you get a newline send command to VESC as PWM then print the string's value

	if (inChar == '\n') {

	  

	  long value = inString.toInt();

	// Send to VESC via PWM

	analogWrite(VescPin, value);  //analogWrite values from 0 (0% duty cycle) to 255 (100% duty cycle)

	// the signal will be sent until you give a new command - so make sure that your main application handles that




	  // Any non integer value will be intercepted here

	  if(value == 0)

	  {

		// send identification lines to PC when asked non-integer string

		// can be used for automatic identification of correct COM-port in Windows app

		Serial.println("VESC Control Arduino");

		// multiline allows detailed description    

		Serial.println("This Arduino accepts integer values and sends a PWM signal to the VESC");   

	  }

	  else

	  {

		// feedback of what the Arduino has been sent

		Serial.print("Value: ");

		Serial.println(value);

	  }

		  

	  // clear the string for new input:

	  inString = "";

	}

  }

}

Hi Der…Jo, Great stuff. These suggestions fill in a lot of the blanks for me. I am trying to get up to speed with the Arduino. I plan to use both your and Maxid’s solutions. Your quick and dirty suggestion makes sense to me and your second idea has me chasing off in a future direction. I need to stay semi focused on the short-term goal of getting the data from my computer to the motor, but please keep any/all suggestions coming. I really do appreciate this.

Hi Maxid, Again, great stuff. I really appreciate the effort on your part. This has me digging into Arduino. I have not used an Arduino so I have spent the last day getting familiar with some of the hardware and software. It is a little unfortunate that a “use it an your own risk” is required. It seems crazy that you putting in your time, effort and experience might invite backlash from someone that demands that any outside assistance must be perfect right out of the gate or else. I just continue to be appreciative of everyones effort with great questions, suggestions and solutions. Please keep it coming.

I simply am not responsible if you break your VESC - as you may know this is new territory for all of us and a prototyp setup. I have personally also not hooked up an Arduino to a VESC so obviously can not guarantee that it will work as intended. Try it and report back!

Will do. PS Staring at my Focbox I feel like I am treating it a little like an “old folk” when they first get their hands on a TV remote and they are reluctant to use it because they think it is kinda like a Star Trek Phaser and they might end up blasting a hole thru their living room wall. If I end up destroying my VESC I can just get another one. I guess when someone says “let’s spark one up” this isn’t what their talking about. P.

Hey there, i’m not totally sure about this but i don’t think simply using analogWrite would be enough to get a readable PWM Signal for the VESC. Instead you could use the Servo library which is included in the Arduino IDE i believe. That would also give you 1024 steps of resolution and worked fine for my VESCs so far. Still, i think using the Vesc Uart Control Library would be the best way to go, it isn’t that much harder to implement and would give you direct control about the numeric rpm value with much more resolution.

No idea - I just looked up how to do PWM and this is what came up.

Do we even need the UART library? All we need is a single command right?

I don’t really know much about serial communication, but as far as i can tell the VESC only accepts it’s own protocol, which is more complicated than a single command. That’s why we need to send the whole package everytime we change one parameter, and that is handled by the library.

servo.h all of that is implemented. This is what i used, it works.

 #include <Servo.h>

Servo myservo;  // create servo object to control a servo

const int ppmMAX = 2000; //max microseconds
const int ppmMIN = 1500;
const int ppmIDLE = 1000;//min 

void setup() {
    Serial.begin(9600);
  myservo.attach(3);  // attaches the servo on pin 3 to the servo object
}


void loop() {
 //fancy code here
 myservo.writeMicroseconds(ppmIDLE); //set ppm to idle
//fancy code
//fancy code
}

It is great that people are thinking through my programming requirements so I thought I should offer up some estimates for what the data might look like.

For my 190 KV 10S 2000W outrunner spinning a 630mm wheel (with 23mm tire), spinning a 25t x 42t crank, I estimate 3.379629 rpm/v. With 4S to 10S I get a crank cadence range from 49 - 122 rpm. This is a no load value and might have to be re-calibrated once the system is under load, but it may not matter as long as everything stays relative.

Below is the middle segment of a warm up/work out/warm down patient set.

Randomized Work Out

Time - Forced Cadence 69s @ 76rpm 28s @ 103rpm 1s @ 52rpm 16s @ 75rpm 90s @ 112rpm 30s @ 118rpm 36s @ 60rpm 70s @ 103rpm 14s @ 115rpm 22s @ 84rpm 68s @ 109rpm 43s @ 106rpm 85s @ 56rpm 3s @ 88rpm 78s @ 108rpm 54s @ 113rpm 73s @ 84rpm 47s @ 79rpm 76s @ 120rpm 3s @ 114rpm

Using 3.379629 rpm/v I get the following duration/voltage data for my motor.

69s @ 22.49v 28s @ 30.48v 1s @ 15.39v 16s @ 22.19v 90s @ 33.13v 30s @ 34.92v 36s @ 17.75v 70s @ 30.48v 14s @ 34.01v 22s @ 24.85v 68s @ 32.25v 43s @ 31.36v 85s @ 16.60v 3s @ 26.04v 78s @ 31.96v 54s @ 33.43v 73s @ 24.85v 47s @ 23.38v 76s @ 35.51v 3s @ 33.73v

If I can hold these type of values with consistent soft transitions I should be good assuming that my presumptions are correct.