Go Down

Topic: Pedelec bicycle - altering controller voltages. Newbie  (Read 350 times) previous topic - next topic

dgncsk

Hello to every body. I have been instersted in arduino projects for some time. Now it is time to advance and learn more.

I have an electric bike with 250w brushless motor. It has a controller, a thumb throttle and control panel.

There are two approaches in ebikes.

1- target power from controller ( you select power and motor never goes above that power level. Such as 20watt, 50watt, 120w, 180w, 250w.

2-target speed. this is soemthing like cruise control on your car. motor turn at full power and when you reach speed set it reduces power and tries to maintain speed.

my controller is 2nd type. this is not ok for low power bikes. i have another bike it is 1st one and it conserves power and makes you pedal more. 2nd is more like scooter with pedals. pedal power is nly required on hills.

So.

Speed limit is controlled by a button. it gets 5 volts constant and gives 2 3 4 volts for correspinding target speeds. lets say 10 15 25 km/h ( this is not important)

Thumb throttle gets 5 volss from controller and gives a continuous 1.8 to 4.8 volts.

which means:

if i can

feed the throttle with 1.8 volts by using 2 volts on Panel, motor turn slow
feed the throttle with 3.2 volts by using 2 volts on Panel, motor turns stronger
feed the throttle with 4.6 volts by using 2 volts on Panel, full power

----

last variable i need to connect signal wire from pedal sensor. it is hall sensor with 3 wires such as the throttle sensor. it gets 5 volts constant, signal from hall sensor output as 5 volt pulses, and a ground.
(frequency of sensor pulses is not important becasue it is only there to understant you are using pedals or not. if no pedal movement, no power. i will use this sensor signal only for arduino not for the original controller input.


i spent all day to understand basics of coding, ( i have some idea about arduino hardware), i tired to do a sketch on circuits.io. i did not add the pedal hall sensor yet. it needs to be acting like on off switch. IR component acts as HALL sensor on circuits.io. you can try it. when you click IR sensor with mouse pointer it works.



Code: [Select]
int PANEL = 0;    // panel voltage
   int val = 0;        
int out = 0;
   int MOTOR = 5;      //output pin
   int spd1 = 102;   //51x   panel  2 volt
   int spd2 = 153; //51x   panel  3 volt
   int spd3 = 204; //51x   panel  5 volt
int thr1 = 92; //1.8volt low power
int thr2 = 163; //3.2volt mid power
int thr3 = 239; //4.6volt hi power

     
     
   void setup() {
     
     Serial.begin(9600);
     
     pinMode(MOTOR, OUTPUT);
   }
   
   void loop() {
    val = analogRead(PANEL);
   
     
     
   if (val <= spd1);  //first step low power
     
     { analogWrite(MOTOR, thr1); }  //thr1 is the preset low power voltage.


//i cant manage to us emultiple conditions to adjust output.
//it always use the first IF statement ignores rest.
   
 
     
     
     
     
     
     Serial.println(val/4);      
         
     delay(500);                    
   }

   

AWOL

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

dgncsk

being rookie... is always hard.  thank you.

i think something like this will work

if (analogRead(pin) >= (4/5)*1024 ) {
analogWrite(pin, (4.5/5)*255);
} else if (analogRead(pin) >= (3/5)*255 ) {
analogWrite(pin, (3.3/5)*255);
} else if (analogRead(pin) >= (2/5)*1024 ) {
analogWrite(pin, (1.2/5)*255);
} else {
analogWrite(pin, 0);
}


i will ask more later. best regards.

AWOL

I'd probably read the pin once and not use arithmetic that yields unexpected results, but maybe that's just me.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

dgncsk

i can try that later. this is DAY 1 with arduino. i got lectures on C language 19 years ago.

here is the updated code. at least it is working somehow.
if you can lead me, it will be greatly appreciated.
https://circuits.io/circuits/5007216-the-unnamed-circuit/embed#breadboard
i managed to made code work. it is not complicated but, i do not understand

a)why medium power setting from control panel cant effect anything?

b)and how to ignore voltages on "panel" other than 1.2 to 4.8 range. i do not want 1.01 volts or 4.99 volts(for instance).  ( because ebike throttle/ and ofcourse speed controller uses only 1.2 to 4.8 volts of 5 volts due to its 3 wire hall sensor)

C) do i need floating point function for intermediate voltage values if needed? how??

Code: [Select]
int val = 0;
int panel = 0;
int thr = 5;
int THR1 = 65;  // preset output preset voltage. 1.2 volts 8 bit
int THR2 = 130; // this one has no effect on output voltage???  3.3 volts...
int THR3 = 245; // preset output preset voltage. 4.8 volts 8 bit
int PNLLO = 409; // constant signal from control panel 2 volt. 10 bit
int PNLMD = 613; // constant signal from control panel 3 volt. 10 bit
int PNLHI = 818; // constant signal from control panel 4 volt. 10 bit

void setup()
{
pinMode(A0, OUTPUT);
Serial.begin(9600);          
}

void loop()

{

val = analogRead(panel);    

if (val == PNLLO) // if panel supplies 2 volts
{
  analogWrite(thr, THR1); // then throttle receives preset voltage 1
}

else if (val == PNLMD) // if panel supplies 3 volts
{
  analogWrite(thr, THR2); // then throttle receives preset voltage 2
}

else if (val == PNLHI) // if panel supplies 4 volts
{  
  analogWrite(thr, THR3); // then throttle receives preset voltage 3
}

else
{
   analogWrite(thr, 0); // ???? below 1.2v THR1 and above 4.8v THR3 must be  ignored. how?
}
Serial.println(val);             // debug value




TomGeorge

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

What model Arduino are you using?
Are you aware that analogWrite command may output a PWM waveform, not a DC level?
This depends on Arduino model you are using.

Thanks.. Tom.. :)
Everything runs on smoke, let the smoke out, it stops running....

TomGeorge

Hi,
OPs circuit.

What values are you getting on your monitor as you adjust the input voltage to A0?

Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

dgncsk

i corrected html code. thanks for pointing that. that is much better now.

i am aware that i have PWM out. i can rectify that later. i need to understand how to program at first.
i was using arduino UNO because circuits.io has that model.
i have arduino mega and a nano. will they be ok?

i get 1.2 volts on multimeter on simulation which is 65 (8 bit) PNLLO power setting on PANEL ( power supply on sim is 2 volts)
i get 0 volts for 130 ( this is what i do not understand) PNLMD ( power supply is 3 volts)
i get 4.7 volts on multimeter on simulation which is 245 PNLHI ( power supply is 4 volts)






dgncsk

i found my mistake. conditions were wrong. because of integers and floating values on PANEL variable, it is shown as 3 votls but its equivalent 10 bit value is not 613. it is 613. something. so i adjusted greater and equal or smaller operators.

Code: [Select]
int val = 0;
int panel = 0;
int thr = 5;
int THR1 = 65;  // preset output preset voltage. 1.2 volts 8 bit
int THR2 = 130; // this one has no effect on output voltage???  3.3 volts...
int THR3 = 245; // preset output preset voltage. 4.8 volts 8 bit
int PNLLO = 409; // constant signal from control panel 2 volt. 10 bit
int PNLMD = 613; // constant signal from control panel 3 volt. 10 bit
int PNLHI = 818; // constant signal from control panel 4 volt. 10 bit

void setup()
{
  pinMode(A0, OUTPUT);
  Serial.begin(9600);          //  setup serial
}

void loop()

{

  val = analogRead(panel);    // read the input pin

  if (val <= PNLLO) // if panel supplies 2 volts
  {
    analogWrite(thr, THR1); // then throttle receives preset voltage 1
  }
 
  else if (val >= PNLMD && val < PNLHI) // if panel supplies 3 volts
  {
    analogWrite(thr, THR2); // then throttle receives preset voltage 2
  }
 
  else if (val >= PNLHI) // if panel supplies 4 volts
  { 
    analogWrite(thr, THR3); // then throttle receives preset voltage 3
  }
 
  else
  {
     analogWrite(thr, 0); // ???? below 1.2v THR1 and above 4.8v THR3 must be  ignored. how?
  }



now need help on attaching a hall sensor (( IR sensor or circuits.io) when IR remote controller is being clicked IR sensor send pulses on signal wire). when there is "click" on IR sensor, arduino must send votlage to thr (5 in this sketch) pin. how can i include this as a primary condition. this is very important becasuse, by circuit work slike a electric scooter. it has 2 volts it runs at  low power continuously, if it is 3 votls i goes faster. if it is 4 volts it goes very fast. one must use pedal to operate system first. this is very important.

pedal hall sensor on bike has 8 magnets on a disk. so it gets signal very fast at 1/8 turn  or 2/8 turn is ok for me. lets say if it sees 2 pulses on hallsensor start loop. if no pulses in 1 second pause my loop. how will i do this?

dgncsk

edit...



dgncsk

i am dealing with hall sensor part of my project. on 4, i am sure i that i need to utilize timer functions.

i checked several codes for putton presses, hall sensor states etc.

since pedals are turning and hall sensor is sending pulses, there are short durations of LOW states which menas no pulses on signal wire to arduino. when pedals get fast it is not that important becasue LOW durations are shorter only. When pedals stop, duration of LOW state, lets say more than 1 sec, motor must stop its rotation. Which means no pedal assist.

HI states are not important right now but if that can be integrated, i can record cadance which is the RPM of pedal. And this can be used to increase power or decrease if required ( on another version of code)


at first, i need to code such thing:


Code: [Select]
if ( Duration of LOW state of hall sensor > 1000) {

// this must be expressed in terms of time. if pedals are not rotating so duration of LOW state will go to infinity. So Loop must stop giving power to throtle. 1 sec or more is ok.

analogWrite(thr, 0);

// 0 volts in terms on 8 bit. or a preset voltage from int THRSTOP = 0; or so.



and i need to code another condition as i suppose PANEL is giving 2 volts to THR and this makes motor turn at low power setting;

that one would be something like:

Code: [Select]
if ((Duration of LOW state < 1000) && (val <= PNLLO)

 // if LOW state is shorter-pedal is turning and panel supplies 2 volts
  {
    analogWrite(thr, THR1); // then throttle receives preset voltage 1
  }

// 2(THR1) 3(THR2) 4(THR3) volts are always there so no need to check it. it is only required to give preset voltage from PANEL to THROTTLE. i will add other condiiton later. now only 2 volts, single power setting)


How can i integrate this two seperate situations inside a loop? i tried to use millis() but it gives always 0 volts as output. Problem is still can not exactly undestand the intterupt logic behind.  if there is a similar code which involves a timer and an output which is dependent to timer, such as running a motor, turning of a light,  if ....timer is < sometime that would be great too. thank you in advance.



dgncsk

I think i did it.

i found a code from http://www.instructables.com/id/Arduino-Bike-Speedometer/ by amandaghassaei in arduino

realized that this can measure the rpm by detecting pulses. there is a complex code at begining. i am not sure why it is there. ( if some one can enlight me i will be happy to learn)

i tweaked code little bit, spent 3 hours. then i modelled the circuti on circuits.io

i utilized a wavegenerator to simulate hall sensor with square wave out put with 2.5volts offset with a frequency setting. lets says 1 Hz. i added a panel to simulate ebike control panel to give 2 3 4 volts when selected. thrtottle is "thr". PNL** are preset panel voltages.

Code: [Select]


//a code from http://www.instructables.com/id/Arduino-Bike-Speedometer/ by amandaghassaei in arduino
//i edited it an added several variables and added my code for my ebike controller.

int hallstate = 0;
int val = 0;
int panel = 5;
int thr = 11;
int THR1 = 65;  // preset output preset voltage. 1.2 volts 8 bit
int THR2 = 130; // this one has no effect on output voltage???  3.3 volts...
int THR3 = 245; // preset output preset voltage. 4.8 volts 8 bit
int PNLLO = 409; // constant signal from control panel 2 volt. 10 bit
int PNLMD = 613; // constant signal from control panel 3 volt. 10 bit
int PNLHI = 818; // constant signal from control panel 4 volt. 10 bit



#define reed A0//pin connected to read switch

//storage variables
int reedVal;
long timer;// time between one full rotation (in ms)
float mph;
float radius = 13.5;// tire radius (in inches)
float circumference;
float kph = 0.00;
float rpm = 0.00; //variable rpm

int maxReedCounter = 100;//min time (in ms) of one rotation (for debouncing)
int reedCounter;
int valreset;


void setup(){
 
  pinMode(A0, INPUT_PULLUP);
 
 
  reedCounter = maxReedCounter;
  circumference = 2*3.14*radius;
  pinMode(reed, INPUT);
 
  // TIMER SETUP- the timer interrupt allows precise timed measurements of the reed switch
  //for more info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
 
  sei();//allow interrupts
  //END TIMER SETUP
 
  Serial.begin(9600);
}


ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
  reedVal = digitalRead(reed);//get val of A0
  val = analogRead(panel);
  if (reedVal){//if reed switch is closed
 
   
    if (reedCounter == 0){//min time between pulses has passed
     
     
      mph = (56.8*float(circumference))/float(timer);//calculate miles per hour
      rpm = float(6000)/float(timer);//calculate rotations per minute
      timer = 0;//reset timer
      reedCounter = maxReedCounter;//reset reedCounter
     
      ;
     
     
     
    }
    else{
      if ((reedCounter > 0) && (val <= PNLLO)){//don't let reedCounter go negative
        reedCounter -= 1;//decrement reedCounter
        analogWrite(thr, THR1);
      }
     
     
     
      else if ((reedCounter > 0) && (val >= PNLMD && val < PNLHI)){//don't let reedCounter go negative
        reedCounter -= 1;//decrement reedCounter
        analogWrite(thr, THR2);
      }
       
      else if ((reedCounter > 0) && (val >= PNLHI)){
        reedCounter -= 1;//decrement reedCounter 
        analogWrite(thr, THR3);
      }
     
     
     
    }
  }
  else {//if reed switch is open
    if (reedCounter > 0){//don't let reedCounter go negative
      reedCounter -= 1;//decrement reedCounter
      ;   
    }
  }
  if (timer > 2000){
    mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
   
   
  }
  else{
   
    timer += 1;//increment timer
   
  }
}

void displayMPH(){
Serial.write(12);//clear

Serial.write(13);//start a new line
kph = mph*1.62;
Serial.println(kph);
Serial.write("Km/h");
}


void loop(){
  //print mph once a second
  displayMPH();
  delay(1000);
  analogWrite(thr, 0); // because no rotation on pedal or wheel - 0 volts in 8 bits.
}




it works. when wave gen is off. no voltage sent to throttle. when generator is on. and when panel voltages selected from voltage source as 2 3 4 volts, multimeter screen shows apporx throttle outputs.

this can show cadance and even could calculate the approx calories burned if duration of total ride could be stored.

could you please evaluate this for me? any mistakes? my eyes are burning.

dgncsk

update. i tried another code. seems simple. i set my bicycle accordingly and i prepared simpe DAC for pw. on output i read programmed values. but... when i attach my hall sensor to related pin and throttle and panel voltages,

this code only works when hall sensor reads magnet not durings the low part of signal. if i keep pedal magnet on hall sensor mtor runs continuously. when magnet passes sensor it stops. it only acts as a switch. how can i embed such "waiting the next pulse from hall sensor for ...... ms" function to this code? could you please help?


Code: [Select]

int panel = A0; //810 panel voltage input pin
int thr = 5; //throttle signal addition wire with a diode on throttle
int THR1 = 90;  // preset output preset voltage. 1.9 volts 8 bit
int THR2 = 130; // 2.5 volts
int THR3 = 185; // 4.8 volts
int PNLLO = 430; // constant signal from control panel 2 volt. 10 bit
int PNLMD = 580; // 3 volt. 10 bit
int PNLHI = 729; // 4 volt. 10 bit
int magnet = 8; //PEDELEC SENSOR Magnet Count to show correct rpm on serial monitor
int val = 0;



//Varibles used for calculations
int ticks = 0, Speed = 0;

int hallsensor = 12;  //The Hall effect sensor pin

//Defines the structure for multiple fans and their dividers
typedef struct{ 

char fantype;
unsigned int fandiv;

}  fanspec; // this is related to hall sensor types.


//set 1 for unipole hall effect sensor
//and 2 for bipole hall effect sensor
fanspec fanspace[3]={{0,1},{1,2},{2,8}}; char fan = 1; // from original code
//fanspec fanspace[3]={{0,1},{1,2},{2,8}}; char fan = 0; // from original code

void pickrpm ()
//This is the interrupt subroutine that increments ticks counts for each HES response.
{ ticks++; }

//This is the setup function where the serial port is initialised,
//and the interrupt is attached and other pins initialized.
void setup()
{
pinMode(hallsensor, INPUT);
Serial.begin(9600);
attachInterrupt(0, pickrpm, RISING);


pinMode(9, OUTPUT); // for leds if needed
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);

digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
}

void loop ()
{

ticks = 0;  // Make ticks zero before starting interrupts.

interrupts();  // or use sei(); to Enables interrupts
delay (1000);  //Wait 1 second
noInterrupts();  //  or use  cli();  to Disable interrupts


Speed = ((ticks * magnet *1.875)/fanspace[fan].fandiv);  // rpm calculation

  Serial.print (Speed, DEC); 
  Serial.print (" RPM\r\n");

val = analogRead(panel); //

// throttle out to controller settings
  if ((Speed > 0) &&(val <= PNLLO)){
 
  analogWrite(thr, THR1);
  }


else if ((Speed > 0)&&((val > PNLMD)&&(val < PNLHI))){
 
  analogWrite(thr, THR2);
  }
  if ((Speed > 0)&&(val > PNLHI)){
 
  analogWrite(thr, THR3);
  }

  if (Speed == 0){
 
  analogWrite(thr, 0);

}
}

Go Up