Position sensor digital read

I have a position sensor like this one.
You can play the video to check how it moves from one end to the other.
Imgur

Using this tutorial, I could have digital readings(serial monitor) from the position sensor.
http://bildr.org/2012/08/rotary-encoder-arduino/
The reading is as below.

0  ----> 0 appears when position sensor is not rotated(left in its original position)
0
0
-1  ----> -1 appears when I rotate position sensor, touching all the way to the end.
-1
-1
-1
-1
-1
0  ----> I let the position sensor go to its original position.
0
0
0
0

I am only getting 0 and -1 from the position sensor. 0 is appeared when I don’t touch the position sensor and -1 appeared when I rotate the position sensor touching all the way to the end. In between, nothing appears.
How can I have digital readings in between from 0(Position sensor in its origial position) to all the way to the other end(Position sensor rotated to the other end)?

This is the code I used for above testing.

//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/

//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {
  Serial.begin (9600);

  pinMode(encoderPin1, INPUT); 
  pinMode(encoderPin2, INPUT);

  digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
  digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

  //call updateEncoder() when any high/low changed seen
  //on interrupt 0 (pin 2), or interrupt 1 (pin 3) 
  attachInterrupt(0, updateEncoder, CHANGE); 
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){ 
  //Do stuff here

  Serial.println(encoderValue);
  delay(1000); //just here to slow down the output, and show it will work  even during a delay
}


void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;

  lastEncoded = encoded; //store this value for next time
}

This is just the same code from the encoder tutorial.

Hi mingki

Do you have a link to details about the sensor you are using? Maybe it encodes position by outputting an analog value, rather than behaving as a rotary encoder.

Regards

Ray

Hi Ray.
How are you?
The pins of this position sensor looks like this.
Imgur
And, this is the pin information.
Pin #1) DC:5V
Pin #2) GROUND
Pin #3) SINGLE (voltage) DC
Pin #4) DC:5V
Pin #5) GROUND
Pin #6) SINGLE (voltage) DC
This is the only information I have.
This sensor supposed to feedback all the variables from 0 to its threshold.

Hi mingki

I'm good, thank you :slight_smile: How are you?

Do you have access to a multimeter? If so, you could check the resistance between GND and signal pin, and then between +5V and signal pin. Maybe the sensor has potentiometers inside, in which case the resistance values would change smoothly as you rotate it. And you could then connect it to an analog pin and see what readings it gives.

What sort of equipment or machine does the sensor come from?

Regards

Ray

Hi, Ray,
I’m fine, thank you so much.
I tried to read the resistance between +5V and signal pin or GND and signal pin but I couldn’t read anything even though I tried rotating the position sensor.
So, I tried putting with analog pin using this tutorial.

And, I used this code.

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() {
   // declare the ledPin as an OUTPUT:
   pinMode(ledPin, OUTPUT);  
}

void loop() {
   // read the value from the sensor:
   sensorValue = analogRead(sensorPin);    
   // turn the ledPin on
   digitalWrite(ledPin, HIGH);  
   // stop the program for <sensorValue> milliseconds:
   delay(sensorValue);          
   // turn the ledPin off:        
   digitalWrite(ledPin, LOW);   
   // stop the program for for <sensorValue> milliseconds:
   delay(sensorValue);                  
}

When the position sensor remain as it is, led pin 13 blinks fast and starts to blink gradually slow if I rotate the position sensor all the way to its end position.
But, I couldn’t have any readings from serial monitor.
My ultimate goal is to display numbers from position sensor to LCD.
I want to know how much this position sensor is moved everytime I rotate this sensor and I want to see on LCD how much this position sensor is moved in percentage. Please help me to pull this off.
My position sensor is from car turbocharger.

But, I couldn't have any readings from serial monitor.

What was the problem? Did you try adding Serial.println(sensorValue); to loop()? And Serial.begin(9600); to setup()?

Hi, Ray.
Thank you so much for helping me out.
I really appreciate it.
Now, I’m getting the readings from serial monitor as below.

96
96    ---> Position sensor in its original position
96
96
96
96
555  ---> Position sensor start to rotate
885  ---> Position sensor fully rotated all the way to the end
885
883
645   ---> Let go of position sensor slowly to go back to its original position
634
621
603
518
433
354
313
250
227
453  ---> Start to rotate again
883
884  ---> Rotated all the way to the end
884
96   ---> Let go of position sensor to go back to its original position
96
97
96
96
97
96
96
96
96
96
94
95
96
96
97
95
97
96
96

And, the program I used is here.

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup() {
   // declare the ledPin as an OUTPUT:
   pinMode(ledPin, OUTPUT);  
   Serial.begin(9600);
}

void loop() {
   // read the value from the sensor:
   sensorValue = analogRead(sensorPin);    
   // turn the ledPin on
   digitalWrite(ledPin, HIGH);  
   // stop the program for <sensorValue> milliseconds:
   delay(sensorValue);          
   // turn the ledPin off:        
   digitalWrite(ledPin, LOW);   
   // stop the program for for <sensorValue> milliseconds:
   delay(sensorValue);       
Serial.println(sensorValue);   
}

When I leave the position sensor in its original position the LED pin 13 blinks rapidly and as I rotate the position sensor, the LED pin 13 blinks slower and slower as the position sensor reachs to the end.
So, it seems that 96 means full closure and 885 means full open of position sensor.
Utilizing such readings from the position sensor, can I use number 96 as 0% and 885 as 100% and then display the status on a LCD like this one. http://www.powertipusa.com/pdf/pc2004m.pdf
I have this LCD from an old electric gadget. I specifically don’t know how to establish a program and how to arrange the wire connections. Please help me.

can I use number 96 as 0% and 885 as 100%

Yes, but …

96
555  ---> Position sensor start to rotate
250
227
453  ---> Start to rotate again

Do some more measurements near the start of movement from original position. The above readings suggest there is a jump near the beginning.

Yes, I did some more measurement by having two type of rotating method.
One is making the rotation slow and steady, the other is making it quick and sudden.
Here is the reading.

96
97
96
96
98
101
102
105
106
108
109
110
110
111
111
110
111
112
112
114
116
120
123
125
126
129
131
132
134
135
140
145
149
151
158
167
172
179
185
194
204
211
220
229
237
251
263
276
287
296
314
346
372
405
471
548
607
688
834
881
881
882
884
883
880
881
880
881
881
881
881
96
95
96
97
96
96
96
186
200
212
251
309
331
495
676
881
510
364
165
112
96
96
96
95
95
95
339
328
513
652
880
96
95
95
95
95
95
97

When I rotate the position sensor quickly, the reading jumps dramatically.

I am getting strange readings on my LCD.
At first, the number starts off with 97 which read from the original position of my position sensor but when the position sensor is rotated a little bit and goes back to its original position, the number becomes 971 or 961.
Imgur
How can I maintain two digit number instead of having three digit number?
This is the code I used.

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
   // declare the ledPin as an OUTPUT:
   pinMode(ledPin, OUTPUT);  
    lcd.begin(16, 2);
    lcd.print("Position Sensor Detector");
   Serial.begin(9600);
}

void loop() {
   // read the value from the sensor:
   sensorValue = analogRead(sensorPin);    
   // turn the ledPin on
   digitalWrite(ledPin, HIGH);  
   // stop the program for <sensorValue> milliseconds:
   delay(sensorValue);          
   // turn the ledPin off:        
   digitalWrite(ledPin, LOW);   
   // stop the program for for <sensorValue> milliseconds:
   delay(sensorValue);    
lcd.setCursor(0, 4 );
lcd.print(sensorValue);
Serial.println(sensorValue);   
}

And, this is the serial monitor readings I had during above test.

96
96
95
118
195
214
246
306
324
432
500
730
766
607
539
438
359
305
284
234
185
157
118
107
100
96
96

The current arrangement in this LCD is not the way I want.
I wanted to arrange it like this. LCD | dsesmg | Flickr

Number 96 means full closure and number 885 means full open of position sensor.
Utilizing such readings from the position sensor, can I use number 96 as 0% and 885 as 100% and then display the status on my LCD?

Hi mingki

the number becomes 971 or 961.

Could the last "1" be left over from a previous, 3-digit reading? If so, you could write 3 spaces each time before you write the actual reading. The spaces would wipe out the previous reading.

lcd.setCursor(0, 4 );
lcd.print("   ");
lcd.setCursor(0, 4 );
lcd.print(sensorValue);

Regards

Ray

Hi Ray,
Thank you so much. Now it works very well.
I don't see any leftover from 3 digit reading anymore.
Could you please teach me how to convert the actual readings to percentage from 0% to 100%?

I searched for converting the actual values and I could came across this tutorial.

I tried according to the tutorial but, I am still having difficulty converting 106 ~ 918(actual reading from position sensor) into 0% ~ 100%.
106 should be 0% and 918 should be 100%.
How can I convert this ?
Right now, I am using this code.

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
   // declare the ledPin as an OUTPUT:
   pinMode(ledPin, OUTPUT);  
    lcd.begin(20, 4);
    lcd.print("Position SensorDetector(%)");
   Serial.begin(9600);
}

void loop() {
   // read the value from the sensor:
   sensorValue = analogRead(sensorPin);    
   // turn the ledPin on
   int positionSensorReading = analogRead(sensorPin);
   float positionSensorVolts = positionSensorReading * 5.0 / 1023.0;
   float positionSensor = (positionSensorVolts - 0.5) * 100.0;
   digitalWrite(ledPin, HIGH);  
   // stop the program for <sensorValue> milliseconds:
   delay(sensorValue);          
   // turn the ledPin off:        
   digitalWrite(ledPin, LOW);   
   // stop the program for for <sensorValue> milliseconds:
   delay(sensorValue);    
lcd.setCursor(0, 4 );
lcd.print("   ");
lcd.setCursor(0, 4 );
lcd.print(sensorValue);
Serial.println(positionSensor);   

}

How do you even know that this device is a position sensor ? It might be a speed sensor.

I tried according to the tutorial but, I am still having difficulty converting 106 ~ 918(actual reading from position sensor) into 0% ~ 100%.
106 should be 0% and 918 should be 100%.

It appears that your device is an analog device with some kind of potentiometer inside it. It is not some kind of rotary encoder, and the normal paradigms for using a rotary encoder would not make much sense for a device that only turns a quarter-turn or so, as it does in your video.

If there is, say, a 10 kiloohm potentiometer inside your device, then it would be quite normal for the resistance at one end of the devices actual travel ( constrained by the mechanism itself, other than the potentiomer ), to be 1 kohm at one end of the device's motion and 9 kohm at the other end of the device's actual motion. The rotation is stopped by some other part of the device structure before it gets to the actual end of the potentiometer's range.

So, it would be quite normal for the analog voltage created by the device to range from 0.5 volts to 4.5 volts, as you are getting. In fact, that may be useful, because then if you get 0 V or 5V, you know the device is broken, disconnected, or short-circuited somehow.

You can rescale the range between 108 and 916 to 0% to 100% if you really want to, but be aware that those values might change depending on the temperature or other factors.

   sensorValue = analogRead(sensorPin);    
   // turn the ledPin on
   int positionSensorReading = analogRead(sensorPin);
   float positionSensorVolts = positionSensorReading * 5.0 / 1023.0;
   float positionSensor = (positionSensorVolts - 0.5) * 100.0;

In this bit of code, you are reading the same pin twice, which is ok, except that you are making your calculations with the second value, but setting your led time delay with the first value, which has the potential to be confusing.

Your percentage calculation in the last line, is wrong. If you analog voltage is 5 V, you would get 450%. Is that what you want ?

If you want 100% to correspond to a voltage of 5V, you would need

float positionSensor = ( ( positionSensorVolts-0.5) / ( 5.0 - 0.5 )) * 100.0 ;

and if you want 100% to correspond to a voltage of, say, 4.6 volts ( which is the maximum you actually see ), then,

float positionSensor = ( ( positionSensorVolts-0.5 ) / ( 4.6 - 0.5 )) * 100.0 ;

Hi michinyon,
Thank you very much!!!
I revised the code like this.

int sensorPin = A0;    // select the input pin for the potentiometer
int ledPin = 13;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
   // declare the ledPin as an OUTPUT:
   pinMode(ledPin, OUTPUT);  
    lcd.begin(20, 4);
    lcd.print("Position SensorDetector(%)");
   Serial.begin(9600);
}

void loop() {
   // read the value from the sensor:
   sensorValue = analogRead(sensorPin);    
   // turn the ledPin on
   int positionSensorReading = analogRead(sensorPin);
   float positionSensorVolts = positionSensorReading * 5.0 / 1023.0;
   float positionSensor = ( ( positionSensorVolts-0.5 ) / ( 4.5 - 0.5 )) * 100.0 ;



   digitalWrite(ledPin, HIGH);  
   // stop the program for <sensorValue> milliseconds:
   delay(sensorValue);          
   // turn the ledPin off:        
   digitalWrite(ledPin, LOW);   
   // stop the program for for <sensorValue> milliseconds:
   delay(sensorValue);    
lcd.setCursor(0, 4 );
lcd.print("   ");
lcd.setCursor(0, 4 );
lcd.print(sensorValue);
lcd.println ("% ");
Serial.println(positionSensor);   
}

And, I could have this readings from the position sensor as I rotate it.

0.20
0.20
0.20
0.08
0.20
0.20
0.20
0.92
5.09
11.05
16.42
19.63
26.55
38.59
47.89
62.31
86.87
97.12
97.24
97.24
97.24
0.32
0.20
0.32
0.20
0.20
0.20
0.32

I could see how the reading gets closer to 100% after changing the code as below according to your advise.

sensorValue = analogRead(sensorPin);    
   // turn the ledPin on
   int positionSensorReading = analogRead(sensorPin);
   float positionSensorVolts = positionSensorReading * 5.0 / 1023.0;
   float positionSensor = ( ( positionSensorVolts-0.5 ) / ( 4.6 - 0.5 )) * 100.0 ;

As per above code, the reading from position sensor when it is fully closed, it is 0.20, and when it is fully opened, it is 97.24.
This is totally fine with me if I could round up the value disregarding the values below decimal point so that the readings could become like this.
0.20 —> 1%
97.24 —> 98%
Please teach me how to do this.
Also, my LCD still shows 104 when the reading is 0.20 on the serial monitor and 918 when the reading is 97.24 on the serial monitor
I need to get 1%, 98% numbers to be displayed on LCD.

I think you are worrying too much about getting exactly 100%. The value is going to fluctuate with vibration and temperature and voltage so there is no point in trying to adjust it too accurately.

Yes, you are right but I am aware of all the variable that might cause data reading fluctuation.
It is just to get the approximation on how much the postion sensor has rotated and I need to monitor this data in percentage on LCD. Please help me to achive this subject.
Your support on this subject would be highly appreciated.

Please help me!!!
I am ready to get it on.
I will try anything.