I need a sketch for wheel encoding odometry inc library please?

Hi all, 

I am trying to control the speed of my DC motors using wheel encoders and reading the speed with an IR LM393 sensor. 

I have downloaded the library for the timer interupt, extracted it into my ardino library (where all my other libraries work)  and I'm still getting..

sketch_nov05a.ino: In function 'void timerIsr()':

sketch_nov05a:14: error: 'Timer1' was not declared in this scope

sketch_nov05a.ino: In function 'void setup()':

sketch_nov05a:30: error: 'Timer1' was not declared in this scope

does anyone have a nice sketch for odometry using the 4 pin sensor I have above (with library) to make my life easier please. 

Many thanks 

Encoders

Please provide details about the physical sensor and library you are using.

Hi Thanks for your

Hi Thanks for your reply,
this is the sensor
http://www.ebay.co.uk/itm/IR-Comparitor-Speed-Sensor-LM393-Module-for-Arduino-Robotics-RPM-and-More-/171968770991?hash=item280a2333af:g:XCYAAOSwyTZUU6DN
and this is his tutorial page with the code and library.
https://brainy-bits.com/tutorials/speed-sensor-with-arduino/
I’m using an uno with adafruit control shield
I’m hoping theres some cleaner/easier code and library for my application, advanced hobbyist/pros must have done this type of thing a million times.
thank you for any help, I do appreciate your time.  

For quadrature encoders I

For quadrature encoders I recently used this:

https://www.pjrc.com/teensy/td_libs_Encoder.html

I got it to compile but I have not yet tested it although he has a video showing how accurate the library is.  It seems pretty simple and straightforward to use and can adapt to what you have for capabilities whether it is polling or interrupts.  

#define ENCODER_OPTIMIZE_INTERRUPTS
#include<Encoder.h>
Encoder leftWheel(2,4) ; 
Encoder rightWheel(3,5) ; 

makes it use interrupts since pins 2 and 3 are interruptable pins on an Arduino Uno. One thing is I had to do was to change the update() in Encoder.h from private to public to make it compile.  Call .read() methods on the encoder objects to get how many ticks it has seen CCW is negative, CW is positive.  Nicely designed class; will see if it works as advertised.

Regards,

Bill 


 

Demo code

The demo code builds for me. I observed 2 problems with the demo code - Serial.print inside a ISR and no delay() in the main loop.

  1. Download TimerOne.zip?
  2. Extract the file to the arduino libraries directory
  3. Do Libraries/TimerOne.h & libraries/TimerOne.h exist in the proper place?

complied

Hi thanks for your reply

 

I am working on it today, the 2 problems you saw…

 

Serial.print inside an ISR

no delay() in the main loop

 

how do I rectify this? please copy and highlight how you would change the code in a reply 

 

many thanks.

 

#include <TimerOne.h>

unsigned int counter=0;

 

int b1a = 6;  // L9110 B-1A 

int b1b = 9;  // L9110 B-1B

 

void docount()  // counts from the speed sensor

{

  counter++;  // increase +1 the counter value

 

void timerIsr()

{

  Timer1.detachInterrupt();  //stop the timer

  Serial.print(“Motor Speed: “); 

  int rotation = (counter / 20);  // divide by number of holes in Disc

  Serial.print(rotation,DEC);  

  Serial.println(” Rotation per seconds”); 

  counter=0;  //  reset counter to zero

  Timer1.attachInterrupt( timerIsr );  //enable the timer

}

 

void setup() 

{

  Serial.begin(9600);

 

 pinMode(b1a, OUTPUT); 

 pinMode(b1b, OUTPUT); 

 

  Timer1.initialize(1000000); // set timer for 1sec

  attachInterrupt(0, docount, RISING);  // increase counter when speed sensor pin goes High

  Timer1.attachInterrupt( timerIsr ); // enable the timer

 

void loop()

{

  int potvalue = analogRead(1);  // Potentiometer connected to Pin A1

  int motorspeed = map(potvalue, 0, 680, 255, 0);

  analogWrite(b1a, motorspeed);  // set speed of motor (0-255)

  digitalWrite(b1b, 1);  // set rotation of motor to Clockwise

}

Serial port inside ISR

My guideline for ISR service time is no more than 20usec. Serial.print functions are multiple milliseconds. 1000 times more. You can pulse an unused I/O pin nd monitor with scope or logic analyzer to measure time or you can follow the code to get an idea. The digitalRead and write function are too slow for ISR use. Lookup examples of direct port I/O.

What is typically done is create shadow copies of variables, ie old_rpm = new_rpm; or set a flag such as new_rpm_available inside the ISR. Then the main loop can check or modify these variable. 1 second is quite a long time for speed control.

I also don’t agree with attach/detach interrupt in the ISR. You want the time base (currently 1 second) to be accurate.

Jsut add delay(xxx) in the main loop where xxx is the number of milliseconds of delay. Sort of accurate. No need to update the PWM as fast as possible. Typically I like to update the PWM between 10 and 100 times per second. 

Hi Max, Alexon from Aphire

Hi Max,

 

Alexon from Aphire here.

All pins on the UNO can be configured to work as interrupts (digital and analogue!) with a little lower level code.

The sketch below required no extra libraries and will fire off some serial prints for two encoders, the wiring is like so:

Encoder 1:
VCC - Some positive power supply
GND - Some ground
A0 - Analog pin 0
D0   - Just leave this with nothing plugged in, don’t need it.
Encoder 2:
VCC  - Some positive power supply
GND - Some ground
A0 - Digital pin 2
D0   - Just leave this with nothing plugged in.

 

void pciSetup(byte pin) 

{

    *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin

    PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt

    PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group 

}

 

// Use one Routine to handle each group

ISR (PCINT1_vect) // handle pin change interrupt for the group pin A0 is in.

 {

     Serial.println(“Encoder 1 ping”);

 }  

 

ISR (PCINT2_vect) // handle pin change interrupt for the group pin D2 is in.

 {

     Serial.println(“Encoder 2 ping”);

 }  

 

void setup() {  

Serial.begin(9600);

Serial.println(":D");

 

  pciSetup(A0);

  pciSetup(2);

}

 

void loop()

{}

He’s alive!

thanks Alexon

 

this code works beautifully, anyone that is tryng to use wheel encoders with an arduino uno will find this will work well.

 

thanks again.