Hi, I’ve two vibe motors alternately on/off with the delay () managed by a pot.
The input was jumpy so I followed the smoothing tutorial. Now the response to me turning the knob is like running through glue. It does speed up / down, but with a 2 second-ish timelag. I’ve 5 elements in my array. Ideas??
Sounds like a coding problem. But I can't see any code so perhaps that isn't it.
Steve
It does speed up / down, but with a 2 second-ish timelag. I've 5 elements in my array.
Those numbers don’t add up. It takes 0.1mS to do one sample so five would be 0.5mS almost three orders of magnitude out from what you say you observe. The sums will take much less time than a sample.
Delay() is in mS intervals not 0.1mS
And we don't what's in the ().
But code would help us to help
Allan
The 0.5ms is the time to call analogRead 5 times for averaging. However the smoothing
tutorial doesn't do this, it calls analogRead() in loop(), and also calls delay(1) in loop().
However it calculates on the fly so that everytime round loop() it calls analogRead() once
and updates the value using a moving average of last N reads.
But its still unclear what the O.P. has done based on that tutorial. Code please!
My first guess is that the smoothing code is still using loop() for repetition but there's also a lot of other stuff in loop() with delays all over the place slowing the repetition rate right down. If we ever see the code we'll know.
Steve
Hi, OK, the code. Now, I can’t get code tags to format this, so apologies up front.
I’ve tried this both with and without the v. motors - leftbuz and rightbuz - attached. The result in the serial monitor or at the motors is the same.
Thanks,
Al
int leftBuz = 3;
int rightBuz = 5;
int potPin = A0;
const int numReadings = 5;
int total = 0;
int readIndex = 0;
int average = 0;
int readings [numReadings];
int thisReading = 0;
void setup()
{
for (thisReading = 0; thisReading < numReadings; thisReading ++){
readings [thisReading] = 0;
}
pinMode(leftBuz,OUTPUT);
pinMode (rightBuz, OUTPUT);
pinMode (potPin, INPUT);
Serial.begin (9600);
}
void loop()
{
total = total - readings [readIndex];
readings [readIndex] = analogRead (potPin);
total = total + readings [readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0;
}
average = total / numReadings;
Serial.println (average);
delay (1);
digitalWrite(leftBuz, HIGH);
delay (average);
digitalWrite(leftBuz,LOW);
delay (average);
digitalWrite (rightBuz, HIGH);
delay (average);
digitalWrite (rightBuz, LOW);
delay (average);
}
That was good guess of mine. You have 4 delays of (average) milliseconds at the end of every loop() before it can loop round and read the next analog value for the smoothing. That's why it takes so long to do anything.
The smoothing code needs to be in it's own loop and you should only do the writes when it has finished a set of X reads (you said you were doing 20 reads but the code says you're doing 5).
Steve
Thanks folks. OK, that makes sense. Can you tell what structure I need? I’ll have a read on structuring my code efficiently.
Physwiz:
Hi, OK, the code. Now, I can’t get code tags to format this, so apologies up front.
If you look in the IDE, EDIT and then "Copy for Forum", the code will be copied with tags attached.
So when you paste into your Forum post, the formatting will have been added.
A look at "Preview" will show your code in Code Format.
Tom.. ![]()
Cheers Tom
Hi, I've taken your advice on my slow and bloated loop. I've started to write a smoothingFn () for the maths, and a vibeFn() for the vibration motors and their delays.
I've read up on and written basic functions that have values passed to them and then return values, but I can't yet make the leap between multiplying integers and writing to the serial monitor, to this.
Can someone help me with calling my two functions within the loop? Thanks, Al
// declarations
int leftBuz=3;
int rightBuz=5;
int potPin = A0;
const int numReadings = 5;
int readings [numReadings];
int thisReading = 0;
int average = 0;
void setup(){
for (thisReading = 0; thisReading < numReadings; thisReading ++){
readings [thisReading] = 0;
}
pinMode(leftBuz,OUTPUT);
pinMode (rightBuz, OUTPUT);
pinMode (potPin, INPUT);
Serial.begin (9600);
}
void loop() {
//empty so far
}
int smoothingFn(){
int total = 0;
int readIndex = 0;
total = total - readings [readIndex];
readings [readIndex] = analogRead (potPin);
total = total + readings [readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0;
}
average = total / numReadings;
Serial.println (average);
return average;
}
int vibeFn(){
digitalWrite(leftBuz, HIGH);
delay (average);
digitalWrite(leftBuz,LOW);
delay (average);
digitalWrite (rightBuz, HIGH);
delay (average);
digitalWrite (rightBuz, LOW);
delay (average);
}
‘... only do the writes after a set of x reads’. Slipstick, could you explain this, please? Cheers, Al
It's difficult to see how this is a "general electronics" topic.
int smoothingFn(){
int total = 0;
int readIndex = 0;
Those two variables probably need to be qualified "static"
OK. It’s morphed. Think ‘mission creep’
Have you looked into this?
http://damienclarke.me/code/posts/writing-a-better-noise-reducing-analogread
I use it to smooth pot reading to fly my gliders.
I've often used a moving average for jobs like this...
ave2 += altitude;
ave2 *= (1-1/aveLen);
ave3 = ave2/(aveLen-1);
Once per loop() ( or whatever sample period you choose), I sample altitude = the variable to be averaged.
aveLen is an integer - how many samples to average over. Say 10,20 etc.
All others are floats.
ave3 is the smoothed result. You get a new value every sample.
Allan
Hi,
Try this code, it uses blink without delay to help your buzz outputs and enable continuous update of the delay variable.
Also it takes a 5 element average that is dynamic, it averages the last 5 values, AFTER reading the analogue input.
So it doesn't wait for 5 new values to load.
It has only been tested on the serial monitor, which gives the state of the output and the last 5 values being averaged.
int leftBuz = 3;
int rightBuz = 5;
int potPin = A0;
const int numReadings = 5; // Number of elements in the Averaging array
int total = 0;
int readIndex = 0;
int average = 0;
int readings [numReadings]; // Averaging array
int thisReading = 0;
int potVal;
int buzzState = 0; // 0 = leftBuz HIGH, 1 = leftBuz LOW, 2 = rightBuz HIGH, 3 = rightBuz LOW
unsigned long previousMillis = 0;
unsigned long currentMillis;
int ledState = LOW;
void setup()
{
Serial.begin(9600);
pinMode(leftBuz, OUTPUT);
pinMode (rightBuz, OUTPUT);
pinMode (potPin, INPUT);
for (thisReading = 0; thisReading < numReadings; thisReading ++) // Preload the averaging array
{
readings [thisReading] = analogRead(potPin);
}
Serial.println(" RunningAverage5_TG2 ");
}
void loop()
{
GetPotValsAverage();
Monitordisplay();
currentMillis = millis();
if (currentMillis - previousMillis >= average) {
// save the last time you switches case
previousMillis = currentMillis;
buzzState = buzzState + 1;
if (buzzState > 4)
{
buzzState = 0;
}
}
switch (buzzState) {
case 0:
digitalWrite(leftBuz, HIGH);
break;
case 1:
digitalWrite(leftBuz, LOW);
break;
case 2:
digitalWrite(rightBuz, HIGH);
break;
case 3:
digitalWrite(rightBuz, LOW);
break;
}
}
//=====================
void GetPotValsAverage()
{
potVal = analogRead(potPin); // Read Pot
for ( int i = 3; i > -1 ; i = i - 1)
{
readings[i + 1] = readings[i]; // Shift preveious readings along the array one step.
}
readings[0] = potVal; // Add the new pot reading as the [0] element a the array
total = 0;
for (int i = 0; i < 5; i = i + 1)
{
total = total + readings[i]; // Total the array
}
average = total / numReadings; // Average the array.
}
//======================
void Monitordisplay()
{
for (int i = 0; i < numReadings; i = i + 1)
{
Serial.print(readings[i]);
Serial.print("\t ");
}
Serial.print("Average = ");
Serial.print(average);
Serial.print("mseconds");
Serial.print("\t buzzState = ");
Serial.println(buzzState);
}
Tom... ![]()
void GetPotValsAverage()
{
potVal = analogRead(potPin); // Read Pot
for ( int i = 3; i > -1 ; i = i - 1)
{
readings[i + 1] = readings[i]; // Shift preveious readings along the array one step.
}
Don't move the data, move the pointer!
AWOL:
Don't move the data, move the pointer!
Its only 5 elements.... and I didn't want to confuse the OP while getting the idea of functions and non delay blinking and switch..case.
But pointers would be better if more elements involved.
Tom.... ![]()
(Ahhh just had first cup of coffee for the day..)