IR Rotary encoder - Debug

So I have built a rotary encorder using IR sender receiver. My problem is I need it to print a 1 only once for every time the black mark goes past, but it prints multiple 1’s every time the mark passes even though it shouldn’t. Any help would be appreciated :slight_smile: Thanks

int powerPinSender= 7;
int powerPinReceiver = 6;

int sensorPin = A0;

int stopStartButton = 9;
int sendDataButton = 8;

int sensorValue = 0;
int value = 1;
int lastValue = HIGH;
int Write = 0;

int ledState = 1;
int pulse = 0;

void setup()
{
  Serial.begin(9600);
  
  pinMode(powerPinSender, OUTPUT);
  pinMode(powerPinReceiver, OUTPUT);
  
  pinMode(stopStartButton, INPUT);
  pinMode(sendDataButton, INPUT);
  pinMode(sensorPin, INPUT);
 
  digitalWrite(powerPinSender,HIGH);
  digitalWrite(powerPinReceiver, HIGH);
 
}

void loop()
{
  sensorValue = analogRead(sensorPin);
  
  if (sensorValue <= 10 && value == 1){
    value = 0;
  }
  if (sensorValue > 10 && value == 1){
    value = 0;
    lastValue = HIGH;
  }
  if (sensorValue <= 10 && value == 0){
    value = 1;
  }
  if (sensorValue > 10 && value == 0 ){
    value = 0;
    lastValue = HIGH;
  }
    
     
  Serial.println(value);
  delay(500);
}

What is there in your code that should stop the multiple printing ?

You should only print value when it has changed from 0 to 1 since the last time it was printed. You have a lastValue variable in your code but don't use it anywhere.

That delay() is not good, either. That will severely, limit the speed that the rotary encoder can measure.

The delay was just there for debugging purposes. The lastValue int was there from another method I tried. Its only printing the value for debugging. When I've got it calling the 1 once per cycle, it will be divided by millis to give the rpm. The problem is even if i have it just print the value 1 instead of changing the value and having it print value, it won't print anything then

int powerPinSender= 7;
int powerPinReceiver = 6;

int sensorPin = A0;

int stopStartButton = 9;
int sendDataButton = 8;

int sensorValue = 0;
int value = 0;
int lastValue = HIGH;
int Write = 0;

int ledState = 1;
int pulse = 0;

void setup()
{
  Serial.begin(9600);
  
  pinMode(powerPinSender, OUTPUT);
  pinMode(powerPinReceiver, OUTPUT);
  
  pinMode(stopStartButton, INPUT);
  pinMode(sendDataButton, INPUT);
  pinMode(sensorPin, INPUT);
 
  digitalWrite(powerPinSender,HIGH);
  digitalWrite(powerPinReceiver, HIGH);
 
}

void loop()
{
  sensorValue = analogRead(sensorPin);
  
  if (sensorValue <= 10 && lastValue == HIGH){
    value = 1;
    lastValue = LOW;
  }
  if (sensorValue > 10 && lastValue == LOW){
    value = 0;
    lastValue = HIGH;
  }
  if (sensorValue <= 10 && lastValue == LOW){
    value = 0;
    lastValue = LOW;
  }
  if (sensorValue > 10 && lastValue == HIGH){
    value = 0;
    lastValue = HIGH;
  }
     
  Serial.println(value);
  delay(500);
}

This didn’t work either

This didn't work either

You are right. It didn't. The posted code does something, but you haven't explained what. You expected it to do something, but you haven't explained what. What doesn't work is expecting help under those circumstances.

Sorry I’m not used to posting for help on code. I wanted to use the lastValue int to discern whether the sensor was over the black or white portion last time the the loop function was performed. The black tape gives a very low IR reflectance so I figured when sensorValue <10 and the lastValue is HIGH it should give a 1, under any other circumstances it should give a zero and if the last number printed was 1 then it should 0 and set lastValue to LOW.

What is happening is it is detecting whether or not it is on the black or white section and spitting out 1’s and 0’s into the serial monitor, but it should only spit out one 1 for every time the sensorValue dips below 10. Something is wrong with the logic, and the lastValue part is not acting as I would expect. The first piece of code is basically the same thing but uses the current value to determine where the black stripe is rather than a lastValue int. I hope this helps

int powerPinSender= 7;
int powerPinReceiver = 6;

int sensorPin = A0;
boolean stripe = HIGH;
boolean lastStripe = HIGH;
int sensorValue = 0;
int value = 0;

void setup()
{
  Serial.begin(9600);
  
  pinMode(powerPinSender, OUTPUT);
  pinMode(powerPinReceiver, OUTPUT);
 
  pinMode(sensorPin, INPUT);
 
  digitalWrite(powerPinSender,HIGH);
  digitalWrite(powerPinReceiver, HIGH);
 
}

void loop()
{
  sensorValue = analogRead(sensorPin);
  
  if (sensorValue < 10 & lastStripe ==HIGH)
  {
    stripe = LOW;
    lastStripe = LOW;
    value = 0;
  }
  if (sensorValue < 10 & lastStripe ==LOW)
  {
    stripe = LOW;
    lastStripe = LOW;
    value = 2;
  }
  if (sensorValue >= 10 & lastStripe ==LOW)
  {
    stripe = HIGH;
    lastStripe = HIGH;
    value = 3;
  }
  if (sensorValue >= 10 & lastStripe ==HIGH)
  {
    stripe = HIGH;
    lastStripe = HIGH;
    value = 4;
  }
  

  Serial.println(value);
  delay(500);
}

using this, the serial monitor only show 2’s and 4’s, when it should show 4 4 4 4, 0, 2,2 ,2, 3, 4, 4, 4… etc. 4 where its white, 0 when it changes from white to black, 2 for black to black, and 3 for black to white.

Why are you expecting us to debug your code for you, when it would be so much easier, and faster, for you to do it?

What value are you actually reading from the sensor? Do NOT assume you know the value!

What value IS in lastStripe? Do NOT assume that you know the value!

Use names that mean something. value means nothing. You might as well call the variable hg5us.

stripe is never used. Why set it?

boolean variables are intended to hold TRUE or FALSE, not HIGH or LOW. Use the correct type (byte).

I don't expect you to do anything for me, I'm asking you to help me because I am struggling to do it.

When over the white part, it reads a value between 30 and 35, over the black part it reads 0 or 1. That is the value of sensorValue.

The value of lastStripe is set LOW (it should have been false, you are right) if the last stripe was less than 10, or HIGH (now true) if greater than 10.

value does mean nothing. It is simply there so I can see which if statement is being called in the serial monitor. What is happening is statements I'm not expecting are being called.

Stripe was there from a previous effort to get it working.

My mistake, I'm new to programming.

Btw, I posted this to a friend, explained my issue, and he said change the last three "if"'s to "else if" and it works as it should now. Thanks for all your help.

Also HIGH and LOW are Booleans, they are used in the examples here: && - Arduino Reference

I'm happy that you got your code working. But, you need to reread the page you linked. Just because HIGH and LOW are mentioned on that page does NOT mean that they should be assigned to boolean variables. While they actually have the same values as TRUE and FALSE, boolean variables should only be assigned values of TRUE or FALSE.

When you want to use other values, use another type.

The next step, when you showed the values of sensorValue and lastStripe, was going to be to have you add print statements inside the 4 blocks that you have. That would have immediately pointed out that multiple blocks were being executed.

But, the point was to try to teach YOU how to debug a program. I already know how, and I already know that it is the least pleasant part of programming.

I'd have had you add the extra print statements all at once, but the idea is to collect some data, analyze it, and determine what other data is needed. If sensorData is consistently correct, then the focus is on how/where the data is used, rather than on why the value is inconsistent/incorrect. If lastStripe is consistently correct, then the focus is on one part of the code. If not, as in your case, the focus should be elsewhere.

Here are the last 3 lines of your loop() function

  Serial.println(value);
  delay(500);
}

You can do as many checks as you like before those 3 lines but the value variable will be printed each time the loop() function executes, whether or not it has changed since last time through loop(). You need to check whether it has changed and only print it if it has.
In pseudo code

if value has changed since last printed
    print value
end of if