Hello to all!
I have modified a piece of code to read an LPD3806-400BM optical encoder, and give me a readout of 1-400 using only one of its outputs. Direction isn't important to me as I just need to be able to count by rotation either way.
Here it is...
/*
In this example, we're using optical encoder LPD3806-400BM.
Only OUT-B (white wire) is used and connected to pin 2 on Arduino.
This allows a count of up to 400 pulses only.
Connecting both outputs will give a count of up to 800 pulses!
*/
volatile long temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
void setup() {
Serial.begin (9600);
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
//Setting up interrupt
//A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
attachInterrupt(0, ai0, RISING);
}
void loop() {
// Send the value of counter
if ( counter != temp ) {
Serial.println (counter);
temp = counter;
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
if (digitalRead(2) == LOW) {
counter--;
if (counter == 0)
counter = 400;
}
else {
if (counter == 400)
counter = 0;
counter++;
}
}
What I am trying to learn for the time being is to be able to turn on an LED when the pulse count reads 100. This LED needs to be on for 500ms or so and whilst I can get it to work using a simple "delay(500);", it will cause issues further down the road.
I've tried using the "blink without delay" code to get me started but to no avail. With these changes I'm not getting any LED turning on at 100.
/*
In this example, we're using optical encoder LPD3806-400BM.
Only OUT-B (white wire) is used and connected to pin 2 on Arduino.
This allows a count of up to 400 pulses only.
Connecting both outputs will give a count of up to 800 pulses!
*/
const int ledPin = LED_BUILTIN;
int ledState = LOW;
unsigned long previousMillis = 0;
const long interval = 500;
volatile long temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
void setup() {
Serial.begin (9600);
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
pinMode(ledPin, OUTPUT);
//Setting up interrupt
//A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
attachInterrupt(0, ai0, RISING);
}
void loop() {
unsigned long currentMillis = millis();
// Send the value of counter
if ( counter != temp ) {
Serial.println (counter);
temp = counter;
}
if (currentMillis - previousMillis == interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
if(counter == 100) {
digitalWrite(ledPin, ledState);
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
if (digitalRead(2) == LOW) {
counter--;
if (counter == 0)
counter = 400;
}
else {
if (counter == 400)
counter = 0;
counter++;
}
}
Your code should set a boolean flag to true when the count becomes 100 then in loop(), if the boolean is true turn on the LED, save the start time and set the boolean to false. Each time round loop() test whether the period has elapsed and, if so, turn off the LED
/*
In this example, we're using optical encoder LPD3806-400BM.
Only OUT-B (white wire) is used and connected to pin 2 on Arduino.
This allows a count of up to 400 pulses only.
Connecting both outputs will give a count of up to 800 pulses!
*/
const int ledPin = LED_BUILTIN;
unsigned long startTime;
int lastCounterReading = 0;
int ledState;
unsigned long interval = 200;
volatile long temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
void setup() {
Serial.begin (9600);
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
pinMode(ledPin, OUTPUT);
//Setting up interrupt
//A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
attachInterrupt(0, ai0, RISING);
}
void loop() {
// Send the value of counter
if( counter != temp ){
Serial.println (counter);
temp = counter;
}
if (counter == 100)
{
if (lastCounterReading != 100)
{
ledState = 1;
startTime = millis();
}
}
lastCounterReading = counter;
if (ledState)
{
if (millis() - startTime <= interval)
{
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
ledState = 0;
}
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
if(digitalRead(2)==LOW) {
counter--;
if (counter == 0)
counter = 400;
}
else {
if (counter == 400)
counter = 0;
counter++;
}
}
The only issue I have now is reading the encoder accurately. If I spin it too fast, Arduino misses 'pulse 100'. Should I use both the encoder's outputs? Would that make a difference? I could use possibly 95-100 as the trigger for the LED if needs be but I'm sure there's a better way as I'm only hand cranking the encoder. Usually these models can track a motor I think.
The other problem is that you are abusing volatile variables. When you use them you need to turn interrupts off. temp doesn't need to be volatile, but you should turn them off when you use counter. In your check for 100, use temp instead.
into the code it still behaves as before wildbill.
Like this...
/*
In this example, we're using optical encoder LPD3806-400BM.
Only OUT-B (white wire) is used and connected to pin 2 on Arduino.
This allows a count of up to 400 pulses only.
Connecting both outputs will give a count of up to 800 pulses!
*/
const int ledPin = LED_BUILTIN;
unsigned long startTime;
int lastCounterReading = 0;
int ledState;
unsigned long interval = 50;
int lastTempReading = 0;
volatile long temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
void setup() {
Serial.begin (250000);
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
pinMode(ledPin, OUTPUT);
//Setting up interrupt
//A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
attachInterrupt(0, ai0, RISING);
}
void loop() {
// Send the value of counter
noInterrupts() ;
if ( counter != temp ) {
Serial.println (counter);
temp = counter;
}
interrupts();
if (counter == 100)
{
if (lastCounterReading != 100)
{
ledState = 1;
startTime = millis();
}
}
lastCounterReading = counter;
if (ledState)
{
if (millis() - startTime <= interval)
{
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
ledState = 0;
}
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
if (digitalRead(2) == LOW) {
counter--;
if (counter == 0)
counter = 400;
}
else {
if (counter == 400)
counter = 0;
counter++;
}
}
However, if I do this...
/*
In this example, we're using optical encoder LPD3806-400BM.
Only OUT-B (white wire) is used and connected to pin 2 on Arduino.
This allows a count of up to 400 pulses only.
Connecting both outputs will give a count of up to 800 pulses!
*/
const int ledPin = LED_BUILTIN;
unsigned long startTime;
int lastCounterReading = 0;
int ledState;
unsigned long interval = 50;
int lastTempReading = 0;
volatile long temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
void setup() {
Serial.begin (250000);
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
pinMode(ledPin, OUTPUT);
//Setting up interrupt
//A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
attachInterrupt(0, ai0, RISING);
}
void loop() {
// Send the value of counter
if( counter != temp ){
Serial.println (counter);
temp = counter;
}
if (temp == 100)
{
if (lastTempReading != 100)
{
ledState = 1;
startTime = millis();
}
}
lastCounterReading = counter;
if (ledState)
{
if (millis() - startTime <= interval)
{
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
ledState = 0;
}
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
if(digitalRead(2)==LOW) {
counter--;
if (counter == 0)
counter = 400;
}
else {
if (counter == 400)
counter = 0;
counter++;
}
}