Pages: 1 ... 3 4 [5] 6 7 ... 9   Go Down
Author Topic: From linear to exponential PWM output  (Read 18515 times)
0 Members and 1 Guest are viewing this topic.
The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This worked. smiley

Code:
if (speedstartValue != speedstartValueold)
     {
     tempMillis = millis() + 3000;
     digitalWrite(led11Pin,HIGH);
     }
if (tempMillis != 0  &&  millis() > tempMillis)
{
     //EEPROM.write(2,speedstartValue);
     speedstartValueold = speedstartValue;
     tempMillis = 0;
     digitalWrite(led11Pin,LOW);
}
Logged

Never to old to learn and I learn every day

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If I add the previous code snippet to other values I thougth it would perform with the same tempMillis lines OK.
Code:
  // +++++ Write values to EEPROM when they change after 3 seconds
  if (speedstartValue != speedstartValueold)
  {
    tempMillis = millis() + 3000;
    digitalWrite(led11Pin,HIGH);
  }
  if (tempMillis != 0  &&  millis() > tempMillis)
  {
    EEPROM.write(2,speedstartValue);
    speedstartValueold = speedstartValue;
    tempMillis = 0;
    digitalWrite(led11Pin,LOW);
  }

  if (speedcurveValue != speedcurveValueold)
  {
    tempMillis = millis() + 3000;
    digitalWrite(led11Pin,HIGH);
  }
  if (tempMillis != 0  &&  millis() > tempMillis)
  {
    EEPROM.write(3,speedcurveValue);
    speedcurveValueold = speedcurveValue;
    tempMillis = 0;
    digitalWrite(led11Pin,LOW);
  }   

  if (brakeNValue != brakeNValueold)
  {
    tempMillis = millis() + 3000;
    digitalWrite(led11Pin,HIGH);
  }
  if (tempMillis != 0  &&  millis() > tempMillis)
  {
    EEPROM.write(4,brakeNValue);
    brakeNValueold = brakeNValue;
    tempMillis = 0;
    digitalWrite(led11Pin,LOW);
  }
Although the led is ON the changed values are not saved except for the speedstartValue.

But I have to declare temp(Xnumber up)Millis for each extra value I like to save to memory.
Is this a correct behaviour? If these extra millis() are running 10 in total could the program freeze as a result of the large number of millis()
Free Sram 5389 still.
Any workaround if this is the case?

Code:
  // +++++ Write values to EEPROM when they change after 3 seconds
  if (speedstartValue != speedstartValueold)
  {
    tempMillis = millis() + 3000;
    digitalWrite(led11Pin,HIGH);
  }
  if (tempMillis != 0  &&  millis() > tempMillis)
  {
    EEPROM.write(2,speedstartValue);
    speedstartValueold = speedstartValue;
    tempMillis = 0;
    digitalWrite(led11Pin,LOW);
  }

  if (speedcurveValue != speedcurveValueold)
  {
    temp2Millis = millis() + 3000;
    digitalWrite(led11Pin,HIGH);
  }
  if (temp2Millis != 0  &&  millis() > temp2Millis)
  {
    EEPROM.write(3,speedcurveValue);
    speedcurveValueold = speedcurveValue;
    temp2Millis = 0;
    digitalWrite(led11Pin,LOW);
  }   

  if (brakeNValue != brakeNValueold)
  {
    temp3Millis = millis() + 3000;
    digitalWrite(led11Pin,HIGH);
  }
  if (temp3Millis != 0  &&  millis() > temp3Millis)
  {
    EEPROM.write(4,brakeNValue);
    brakeNValueold = brakeNValue;
    temp3Millis = 0;
    digitalWrite(led11Pin,LOW);
  }

Paco
Logged

Never to old to learn and I learn every day

Offline Offline
Full Member
***
Karma: 0
Posts: 162
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You do not need to keep reading the time with repeated calls to millis().
Read it once at the beginning of the loop and put the value in a variable.  Everything in the loop then references currentTime.
Also a separate, reasonably-named variable for each turn off time is a reasonable expense.
Code:
currentTime = millis();
....

if (brakeNValue != brakeNValueold)
{
      brakeOffTime = currentTime  + 3000;
      digitalWrite(led11Pin,HIGH);
}
if (brakeOffTime != 0  &&  currentTime   > brakeOffTime )
{
      EEPROM.write(4,brakeNValue);
      brakeNValueold = brakeNValue;
      brakeOffTime = 0;
      digitalWrite(led11Pin,LOW);
}
Logged

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Techylah,

I declared in the init part:
long currentTime = millis();
long brakeOffTime = 0;

With your code after power up the led11Pin goes on and not off.
With serial monitor I chekced and see brakeOffTime stays 3000 what ever you do.
So I changed currentTime into millis() and then when I power on the led11Pin is on for 3 secs and after that when I press the key the led goes ON and OFF after the 3 secs. So that works then.....
So why putting millis() into the variable is not working and is of influence on the fact the led11Pin is high always?

Paco
Logged

Never to old to learn and I learn every day

Offline Offline
Full Member
***
Karma: 0
Posts: 162
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The declaration and setting of currentTime goes only in the loop routine, at the beginning.
Throughout that passage through the loop, that is the current time.
The beginning of each loop sets a new currentTime.

All of the turn off times, like long brakeOffTime need to be declared outside of of the loop routine, as global variables,
since they must remain the same for multiple passes of the loop.

So the loop routine starts with:
long currentTime = millis();

Outside both the init and loop routines, you have:
long brakeOffTime = 0;
long speedcurveOfftime = 0;
...


Logged

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Techylah,

Sorry for no response.
Been busy to finalize the hardware so we can test drive the controller this coming friday evening at a track.
I put your recommendations in the code and that works fine now. Thanks again.

I checked all about the look up table discussions but still do not understand.
For my understanding I like to go back to an other version of the speedcurve which is more simple to understand for me I guess and progress from there.
See the attachement.
I also have to make the guys clear what they are doing when they set up speed curve.
Friday I receive a Android phone which I like to connect the controller to display the curve settings (and all other settings).
If the hardware is functioning fine I can always adapt the software settings.

Paco

* scan06062012_00000.pdf (242.21 KB - downloaded 19 times.)
Logged

Never to old to learn and I learn every day

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Got some sort of working code.

Code:
   if (sensormappedValue < switchpointValue)
    speedValue = map(sensormappedValue, 0, 255, speedstartValue, 255); // can be switched off later stage when curve section works.
    else
  //  speedValue = (int) (0.5  +  speedstartValue + pow(sensormappedValue/127.0, gammaSValue) * ((speedfinalValue - speedstartValue) / 2.0) );   
    speedValue = (int) (0.5  +  speedfinalValue - pow((255 - sensormappedValue)/127.0, gammaSValue) * ((speedfinalValue  - speedstartValue) / 2.0));

I added switchpointValue variable instead of the fixed 128 to change the point on the trigger baseline where the linear line is starting to bend. Both options earlier supplied give a drop down in speedfinalvalue after switchpointValue is reached.
I tried to figure out how to change the line to linear climbing after the switchpointValue but I failed sofar.

Paco
Logged

Never to old to learn and I learn every day

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Techylah and Rob,

The maiden trip of the controller was made yesterday evening.
It ran 3 hours without any electronic/mechanical hick up.
I had two fast club drivers trying the controller.
They were very content about the fact they could see what they adjusted for startspeed and break and now knew what they were doing in numbers.

They had only one remark  smiley-confuse at the end of the evening and that is that the controller is not following the trigger movement exactly.
As the controller was programmed for a linear line (curving not working yet) they say there was a lack in response when going from 0 to full speed.
They described it as a delay.
I can not confirm their FEELING but have to believe them.
These guys run rounds measured in 1/1000 of a second!
The difference with my controller and an other known one was 3 tenth of a second.  smiley-red

Could this be caused due to coding delaying the PWM to respond in this case?

Other thoughts and suggestions are welcome.

Paco
Logged

Never to old to learn and I learn every day

Offline Offline
Full Member
***
Karma: 0
Posts: 162
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
They described it as a delay.
I can not confirm their FEELING but have to believe them.
I believe them, too!

I'm pretty sure it is because you are doing calculations on the fly instead of the lookup table.

Replace:
Code:
speedValue = (int) (0.5  +  speedfinalValue - pow((255 - sensormappedValue)/127.0, gammaSValue) * ((speedfinalValue  - speedstartValue) / 2.0));
with
Code:
speedValue = lookupTable[sensormappedValue];
and then, in your init code:
Code:
for (int i=0; i<256; i++)
   lookupTable[i] = (int) (0.5  +  speedfinalValue - pow((255 - i)/127.0, gammaSValue) * ((speedfinalValue  - speedstartValue) / 2.0));

speedValue will be exactly the same but practically instantaneous, instead of after slogging through the really slow floating point implementation of pow(), along with three also slow floating point multiply/divides.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 228
Posts: 14059
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Agree with TechyIah, a lookup table would improve speed, you might place it in PROGMEM to minimize using RAM.
That means you need to print it and make C-code of it ( make a small sketch that prints a C-array)
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Techylah,

Code:
for (int i=0; i<256; i++)

Gives and error in de INIT section.
Expected unqualified-id before "for"
expects contructor,destructor or type conversion before < or ++ token
I googled for it and the code is used more so code is correct.
Must be something in conjunction of the existing code I assume.

Also "lookupTable" needs to be declared as array?

Rob, do not make it more difficult as it is.  smiley-cool One step at the time.

Will look for PROGMEM and what it does.

Paco
Logged

Never to old to learn and I learn every day

Offline Offline
Full Member
***
Karma: 0
Posts: 162
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes,
Code:
char lookupTable[256];
It needs to be declared outside both the init and the loop code.
And yes, get that working first and then go for saving the 256 bytes of RAM by using PROGMEM as Rob points out, if you won't be changing the curve on the fly.
Logged

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Techylah,

So no error codes anymore.

I ran some test but all are different then desired.

I reduced some lines to get the basic without any switchpointValue and only used the lookupTable line.
speedstartValue is set at 1
gammaSValue is set at 1.0

speedfinalValue however in this case is always starting at 171 regardless all other settings.
Also ispeedfinalValue runs through and passing the 255 value going to 0 at the end of full trigger.

Current code for the output.
Code:
void setup()
for (int i=0; i<256; i++)
lookupTable[i] = (int) (0.5  -  speedfinalValue + pow((255 - i)/127.0, gammaSValue) * ((speedfinalValue  - speedstartValue) / 2.0));

void loop()
//  +++++++++++++++  regular speed - brake mode  +++++++++++++++

  // in regular mode control the outputs with output cross block function to prevent speed and brake to be ON together
  sensorValue = analogRead(sensorspeedPin); // read the raw value from the linear hall sensor:
  sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);// apply the calibration to the sensor reading from the hall sensor
  sensormappedValue = constrain (sensorValue,0,255); // keep value in range
 
  //  ++++  curve section  +++++++
   //if (sensormappedValue < (switchpointValue - speedstartValue)) // switchpoint for test set at 120
   //speedValue = map(sensormappedValue, 0, 255, speedstartValue, 255);
   //else
   //speedValue = 0;
   speedValue = lookupTable[sensormappedValue];
  //  ++++  curve section  +++++++

  speedfinalValue = constrain (speedfinalValue, 0, 255);
  speedfinalValue = speedValue;
 

  if (sensormappedValue > deathbandValue)
  {
    analogWrite(pwmoutspeedPin, speedfinalValue);
    analogWrite(pwmoutbrakePin, 0);
    digitalWrite(ledDBPin, LOW);
    digitalWrite(ledBPPin, HIGH);
  }
  else
  {
    analogWrite(pwmoutspeedPin, 0);
    (speedfinalValue, 0);
    analogWrite(pwmoutbrakePin, brakeNValue);
    digitalWrite (ledDBPin,HIGH);
    digitalWrite(ledBPPin, LOW);
  }


Paco
Logged

Never to old to learn and I learn every day

The Netherlands
Offline Offline
Sr. Member
****
Karma: 4
Posts: 333
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Techylah,

For my cofirmation. with the before the init code you mean "void setup()" section?

Paco

Logged

Never to old to learn and I learn every day

Offline Offline
Full Member
***
Karma: 0
Posts: 162
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
For my confirmation. with the before the init code you mean "void setup()" section?
Yes.
Logged

Pages: 1 ... 3 4 [5] 6 7 ... 9   Go Up
Jump to: