No, I thought the 1ms time division in the loop is sufficient to filter out transients. The output on A5 (controller's torque) is shaped by a simulated DAC, basically switching the pin to 5V with a pulse width modulatorHave you got a low pass filter on your Arduino's output to the torque sensor input?
It was the same with the Speedict, which was probably just an Arduino in a wrapper. They provided a special cable for the throttle that had a low pass filter in it. The Speedict took your PAS and throttle and reprocessed them to do some clever things. If you used a normal cable, it worked fine for a few minutes, then seemed to get a mind of its own. A normal controller can't cope with a pwm signal on the throttle input. It has to be smooth analogue.No, I thought the 1ms time division in the loop is sufficient to filter out transients. The output on A5 (controller's torque) is shaped by a simulated DAC, basically switching the pin to 5V with a pulse width modulator
the torque output seems to work OK when the throttle is in charge.
There are two errors: 21 and 22.They provided a special cable for the throttle that had a low pass filter in it. The Speedict took your PAS and throttle and reprocessed them to do some clever things. If you used a normal cable, it worked fine for a few minutes, then seemed to get a mind of its own. A normal controller can't cope with a pwm signal on the throttle input. It has to be smooth analogue.
that may explain what Raj found.Remember a couple of years back, when a guy made a video of his Crossfire with a push-button throttle. All he did was short the throttle signal wire to 5v. He got that idea after his cable got damaged and the bike started going at full speed by itself. I can't find the link now.
Yeah sorry about that, work this week is chaotic but saturday morning and sunday i can help out.Evian could not help much in the last couple of days
// Version 9
// use internal pullup/pulldown resistors on input pins.
// implement low pass filter using recording and playback
const byte ThrottlePin = A0;
const byte CadenceInputPin = A2;
const byte TorqueInputPin = A3;
const byte TorqueOutputPin = A5;
const byte CadenceOutputPin = 13;
const byte TorqueAtRest = 198;
// I am on throttle
int pulseoff = 25; // milliseconds when D13 is low
int pulseon = 25; // milliseconds when D13 is high 4Hz
// I am pedalling.
// I record the cadence pulse first.
bool cadencestate = false;
int cadencepulselength = 991;
int cadencepulseonlength = 0;
int cadencepulseofflength = 0;
unsigned long torqueontotal =0;
unsigned long torqueofftotal =0;
// then play it back, average values are used to implement low pass filter
int playbackpulseon = 25;
int playbackpulseoff = 25;
int playbacktorqueon = 0;
int playbacktorqueoff = 0;
bool pulse = false;
unsigned long startMillis;
unsigned long currentMillis;
void setup() {
pinMode(CadenceOutputPin, OUTPUT);
pinMode(TorqueInputPin, INPUT_PULLUP); // cadence input default high
pinMode(TorqueOutputPin, OUTPUT); //ControllerTorquePin
pinMode(CadenceInputPin, INPUT); //PASCadencePin
digitalWrite(TorqueOutputPin, LOW);
startMillis = millis();
// Serial.begin(9600);
}
void loop() {
if (millis()>currentMillis) // run once every millisecond
{
currentMillis = millis();
// ****** Start recording current pulse ******
if (cadencepulselength < 1000) cadencepulselength++;
if (cadencestate)
{
// on cadencestate transtion from high to low, reset cadencepulselength and transfer accummulator to playback
if (analogRead(CadenceInputPin) < 512)
{
cadencepulselength = 0;
cadencestate = false;
playbackpulseon = pulseonlength;
playbackpulseoff = pulseofflength;
if (pulseonlength >0) playbacktorqueon = torqueontotal/pulseonlength;
if (pulseofflength >0) playbacktorqueoff = torqueofftotal/pulseofflength;
torqueontotal = 0;
torqueofftotal = 0;
pulseonlength = 0;
pulseofflength = 0;
}
else // continue with pulse high
{
pulseonlength++;
torqueontotal = torqueontotal + analogRead(torqueInputPin)/4;
}
}
else // if cadencestate is low
{
if (analogRead(CadenceInputPin) < 512) // continue with pulse low
{
pulseofflength++;
torqueofftotal = torqueofftotal + analogRead(torqueInputPin)/4;
}
}
if (analogRead(CadenceInputPin) > 512) cadencestate = true;
if (cadencepulselength > 200) // defaults when stopping
{
cadencestate = true;
torqueofftotal =0 ;
torqueontotal =0;
}
// ****** end recording current pulse ******
// check throttle
int torqueval = analogRead(ThrottlePin) / 4; // Read the value from the throttle pin A0
if (torqueval < 75) // disable throttle if voltage < 1.5V
{
// ****** I'm pedalling, play back last pulse *****
pulse = true;
if (currentMillis > (startMillis + playbackpulseon)) pulse = false;
if (currentMillis > (startMillis + playbackpulseon + playbackpulseoff)) startMillis = millis(); // reset timer clock
if (pulse)
{
digitalWrite(CadenceOutputPin, HIGH);
analogWrite(TorqueOutputPin, playbacktorqueon);
}
else
{
digitalWrite(CadenceOutputPin, LOW);
analogWrite(TorqueOutputPin, playbacktorqueoff);
}
// ****** end play back last pulse *****
}
else
{
//I'm using the throttle
analogWrite(TorqueOutputPin, torqueval);
pulse = true;
if (currentMillis > (startMillis + pulseon)) pulse = false;
if (currentMillis > (startMillis + pulseon + pulseoff)) startMillis = millis(); // reset timer clock
if (pulse) digitalWrite(CadenceOutputPin, HIGH);
else digitalWrite(CadenceOutputPin, LOW);
}
}
}
Looks like INPUT_PULLDOWN isn't valid on an Arduino Nano. Receiving the "INPUT_PULLDOWN was not declared in this scope" error.I have revised the code to addres vfr400's comments.
1. controller's non zero start: cadence input set to input_pulldown, torque input set to input_pullup.
2. low pass filter: previous code had 1ms time division for low pass, new code has half pulse (about 25ms) time division. New code records the current pulse and plays it back 1 pulse later.
Code:// Version 9 // use internal pullup/pulldown resistors on input pins. // implement low pass filter using recording and playback const byte ThrottlePin = A0; const byte CadenceInputPin = A2; const byte TorqueInputPin = A3; const byte TorqueOutputPin = A5; const byte CadenceOutputPin = 13; const byte TorqueAtRest = 198; // I am on throttle int pulseoff = 25; // milliseconds when D13 is low int pulseon = 25; // milliseconds when D13 is high 4Hz // I am pedalling. // I record the cadence pulse first. bool cadencestate = false; int cadencepulselength = 991; int cadencepulseonlength = 0; int cadencepulseofflength = 0; unsigned long torqueontotal =0; unsigned long torqueofftotal =0; // then play it back, average values are used to implement low pass filter int playbackpulseon = 25; int playbackpulseoff = 25; int playbacktorqueon = 0; int playbacktorqueoff = 0; bool pulse = false; unsigned long startMillis; unsigned long currentMillis; void setup() { pinMode(CadenceOutputPin, OUTPUT); pinMode(TorqueInputPin, INPUT_PULLUP); // cadence input default high pinMode(TorqueOutputPin, OUTPUT); //ControllerTorquePin pinMode(CadenceInputPin, INPUT_PULLDOWN); //PASCadencePin default low digitalWrite(TorqueOutputPin, LOW); startMillis = millis(); // Serial.begin(9600); } void loop() { if (millis()>currentMillis) // run once every millisecond { currentMillis = millis(); // ****** Start recording current pulse ****** if (cadencepulselength < 1000) cadencepulselength++; if (cadencestate) { // on cadencestate transtion from high to low, reset cadencepulselength and transfer accummulator to playback if (analogRead(CadenceInputPin) < 512) { cadencepulselength = 0; cadencestate = false; playbackpulseon = pulseonlength; playbackpulseoff = pulseofflength; if (pulseonlength >0) playbacktorqueon = torqueontotal/pulseonlength; if (pulseofflength >0) playbacktorqueoff = torqueofftotal/pulseofflength; torqueontotal = 0; torqueofftotal = 0; pulseonlength = 0; pulseofflength = 0; } else // continue with pulse high { pulseonlength++; torqueontotal = torqueontotal + analogRead(torqueInputPin)/4; } } else // if cadencestate is low { if (analogRead(CadenceInputPin) < 512) // continue with pulse low { pulseofflength++; torqueofftotal = torqueofftotal + analogRead(torqueInputPin)/4; } } if (analogRead(CadenceInputPin) > 512) cadencestate = true; if (cadencepulselength > 200) // defaults when stopping { cadencestate = true; torqueofftotal =0 ; torqueontotal =0; } // ****** end recording current pulse ****** // check throttle int torqueval = analogRead(ThrottlePin) / 4; // Read the value from the throttle pin A0 if (torqueval < 75) // disable throttle if voltage < 1.5V { // ****** I'm pedalling, play back last pulse ***** pulse = true; if (currentMillis > (startMillis + playbackpulseon)) pulse = false; if (currentMillis > (startMillis + playbackpulseon + playbackpulseoff)) startMillis = millis(); // reset timer clock if (pulse) { digitalWrite(CadenceOutputPin, HIGH); analogWrite(TorqueOutputPin, playbacktorqueon); } else { digitalWrite(CadenceOutputPin, LOW); analogWrite(TorqueOutputPin, playbacktorqueoff); } // ****** end play back last pulse ***** } else { //I'm using the throttle analogWrite(TorqueOutputPin, torqueval); pulse = true; if (currentMillis > (startMillis + pulseon)) pulse = false; if (currentMillis > (startMillis + pulseon + pulseoff)) startMillis = millis(); // reset timer clock if (pulse) digitalWrite(CadenceOutputPin, HIGH); else digitalWrite(CadenceOutputPin, LOW); } } }
I have tested the v9 release of the code with the following code changes:Hi Raj, change that line to
pinMode(CadenceInputPin, INPUT);
Yeah I think your right the best version to date is v8.yes, I agree and thank you for testing it out.
I am out of idea at the moment.
The best version is still version 8.
Do you have a resistor across A2-GND?
That's what INPUT_PULLDOWN does.
I was reading this post:this is the wiring that produces error 22 after 3 seconds:
D13 to controller's cadence
A2 to sensor's cadence.
controller's torque to sensor's torque
Can anyone see an explanation?
see post #294
View attachment 41216