Detect change in Arduino potentiometer - arduino

I am trying to write my arduino code to upon detection of a change in the potentiometer analog read value to execute a function.
My question is how do I detect a change in the potentiometer value, I am reading in the potentiometer as normally done, but I am stuck as to how to compare this to see if it has changed.
My loop code for reading potentiometer value:
void loop()
{
val = analogRead(potpin);
val = map(val, 0, 1023, 0, 179);
Serial.println(val);
delay(15);
if (val >= 90)
{
sendSMS5();
delay(10000);
switchOff();
}
}
I am thinking that maybe a number of IF statments to compare if the value falls into a certain bracket is the only way to do this.

Save the value in a variable declared outside the loop.
#define TOLERANCE 10
int oldVal = 0;
void loop()
{
val = analogRead(potpin);
val = map(val, 0, 1023, 0, 179);
Serial.println(val);
delay(15);
int diff = abs(val - oldVal);
if(diff > TOLERANCE)
{
oldVal = val; // only save if the val has changed enough to avoid slowly drifting
// and so on
}
if (val >= 90)
{
sendSMS5();
delay(10000);
switchOff();
}
}

Related

Can I use float to store millis function return value as done in the code?

Can I use float data type to store the return value of millis function as shown on the code here? I saw unsigned int type to do it. But look I'm converting that millis to hour. That's why I'm trying to store in float.
#include<Servo.h>
#include<math.h>
Servo mark1;
float dur = 2.30, del_dur = 0 ;
float sys_strt = (millis()/3600000), curr_tim = (millis()/3600000), del_strt = 0;
float inc_val;
const int relay_on = 8;
//2, output = 9;
void setup()
{
digitalWrite(8, HIGH);
mark1.attach(9);
mark1.write(110);//servo on
Serial.begin(9600);
// pinMode(switch_on, INPUT);
// pinMode(output, OUTPUT);
}
void loop()
{
if(Serial.available() > 0)
{
inc_val = Serial.read();
Serial.print("\n");
if(inc_val == 'D') // D = DURATION
{
delay(2000);
dur = Serial.read();
sys_strt = (millis()/3600000);
//mark1.write(on);
}
else if(inc_val == 'd') // d = delay_duration_for_future_turn_on
{
mark1.write(158);// servo off
delay(2000);
del_dur = Serial.read();
Serial.print("\n");
delay (5000);
dur = (Serial.read() + del_dur);
del_strt = (curr_tim + del_dur);
sys_strt = del_strt;
//curr_tim = (millis()/1000);
}
}
if((millis()/3600000) >= 5)
{digitalWrite( 8, LOW);}
if(((millis()/3600000) - del_strt) >= 0 && ((millis()/3600000) - del_strt) <=10 ) // statement for delay duration process
{
mark1.write(110);// servo on
}
if(((millis()/3600000)-sys_strt) >= dur)
{
mark1.write(158);//servo off
}
}
//int x = ((millis() / 1000) - off_timer_start) / 60;
// if (digitalRead(switch_on) == HIGH)
//{
// off_timer_start = (millis() / 1000);
//digitalWrite(output, HIGH);
//}
//else if (x >= offtime && digitalRead(output == HIGH)) {
//digitalWrite(output, LOW);
//}
//delay(1000);
I was trying to store millis return value in float variable. But not sure whether it'll work or not.
There is no need to use float, millis() return an unsigned long which is a 32-bit integer (i.e. equivalent to uint32_t).
Instead of doing division, which is more computationally intensive and has to be done in the runtime for thing like millis()/3600000, you could use 5*3600000 (which is a constant, and the compiler will optimize it to a constant of 18000000 during the compilation) for representing 5 hours. So instead of doing
if((millis()/3600000) >= 5) // do something
it can be done as:
if((millis() >= 5*3600000) // do something
or even better you could define the constant to make your code more readable as:
unsigned long fiveHour = 5*3600000;
if ((millis() >= fiveHour) // do something
It appears that the Arduino related millis() function returns unsigned long, so you cannot store it with full precision in a float.

Value of variable doesn't change

I am writing this code for a photoresistor on the arduino. I am supposed to attach servos to the photoresistor so that it will work as a moving solar panel. However, upon running the code I note that the value of variable pos (which is supposed to store the angle having max amount of light) does not change. What can I do about it?
int val1, val2, temp = 1000;
int pos = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
int val = map(sensorValue, 0, 1023, 0, 100);
Serial.println(val);
for(int i=0; i<180; i++){
val1 = map(sensorValue, 0, 1023, 0, 100);
if(val1 <= temp){
temp = val1;
pos = i;
}
delay(15);
}
Serial.println(pos);
delay(1000);
}
As #datafiddler suggested you need to ad the analogRead into the for loop.
Some things I would change in order to have a faster and cleaner code:
change the initialized temp to 100
delete val2
delete code before for loop
longer delay in for loop
here the edited code:
int val = 0;
int temp = 100;
int pos = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
//move servo to pos = 0
for(int i = 0; i < 180; i++){
val = analogRead(A0)
val = map(val, 0, 1023, 0, 100);
if(val <= temp){ //save minimum
temp = val;
pos = i; //save position
}
//move servo
delay(100); //try out what works best with the used servo
}
Serial.println(pos);
delay(1000);
}

Arduino Error: 'val' does not name a type

Some students from my school are working on a project to measure vibrations (eg. earthquakes) and print the results from two sensors (Piezo knock and vibration sensor) to lcd shield. They probably compiled some codes from the internet. Their original code was like this:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int referansDegeri = 800;
int knockSensor = 0;
int val = 0;
int sensorLevel = map;
int statePin = LOW;
int THRESHOLD = 100;
const int analogPin = A0;
int vib_pin=7;
void setup()
{
int sensorReading = analogRead(analogPin);
// map the result to a range from 0 to the number of LEDs:
int sensorLevel = map(sensorReading, 0, 1023, 0, sensorCount);
pinMode(vib_pin,INPUT);
Serial.begin(9600);
}
void loop()
{
int sensorDegeri = analogRead(A0);
Serial.print(sensorDegeri); //Okuduğumuz değer ekrana yazdırılıyor
if (sensorDegeri >= referansDegeri){
Serial.println("siddetli sarsinti");
}
else{
Serial.println("dusuk sarsinti");
}
delay(1);
}
val = analogRead(knockSensor);
if (val >= THRESHOLD) {
statePin = !statePin;
digitalWrite(ledPin, statePin);
Serial.println("Knock!");
delay(100);
int val;
val=digitalRead(vib_pin);
if(val==1)
{
digitalWrite(led_pin,HIGH);
delay(1000);
digitalWrite(led_pin,LOW);
delay(1000);
}
else
digitalWrite(led_pin,LOW);
}
This code gave this error (exit status):
'sensorCount' was not declared in this scope
Knowing that the students have one knock sensor, I changed the sensorCount to 1 while mapping it so it would seem
int sensorLevel = map(sensorReading, 0, 1023, 0, 1);
then it started giving this error (exit status):
'val' does not name a type
I made some search however, could not find a specific result so cannot fix the problem. But I believe it is important to mention that students were using LED Bar Graph previously, alongside LCD shield, but they have now removed it.

Saving Arduino sensor data to text file

I've been working to save data from an accelerometer sensor to a text file. But after searching the web for several hours, the methods I've found haven't worked. Here is the program I have now.
// Accelerometer sensor program
const int ar1 = A5;
const int ar2 = A4;
const int ar3 = A3;
int x = 0;
int ov1 = 0;
int y = 0;
int ov2= 0;
int z = 0;
int ov3= 0;
void setup() {
// initialize the communications
Serial.begin(9600);
}
void loop() {
analogReference(EXTERNAL); //connect 3.3v to AREF
// X axis
// Read the analog
x = analogRead(ar1);
// Range of analog out
ov1 = map(x, 0, 1023, 0, 255);
delay(2);
// Y axis
y = analogRead(ar2);
ov2 = map(y, 0, 1023, 0, 255);
// Z axis
delay(2);
z = analogRead(ar3);
ov3 = map(z, 0, 1023, 0, 255);
// Should print to the monitor
// Output for X axis
Serial.print("Xsensor1 = " );
Serial.print(x);
Serial.print("\t output1 = ");
Serial.println(ov1);
// Output for Y axis
Serial.print("Ysensor2 = " );
Serial.print(y);
Serial.print("\t output2 = ");
Serial.println(ov2);
// Output for Z axis
Serial.print("Zsensor3 = " );
Serial.print(z);
Serial.print("\t output3 = ");
Serial.println(ov3);
// Should repeat every second
delay(1000);
What I've found does seem to do what I want, the issue is that Arduino doesn't want to run it, saying that 'import' was not declared in the scope. I've tried installing some libraries, but I couldn't find the exact library that import is part of, or PrintWriter for that matter. Here is the code causing issues:
import processing.serial.*;
Serial mySerial;
PrintWriter output;
void setup() {
mySerial = new Serial( this, Serial.list()[0], 9600 );
output = createWriter( "data.txt" );
}
void draw() {
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed() {
output.flush(); // Writes the remaining data to the file
output.close(); // Finishes the file
exit(); // Stops the program
}
Thanks in advance.
The code you have isn't for the Arduino but is written in a language called Processing. It will run on your PC and collect the data from the Arduino to be saved to a file. You need to download the Processing IDE to compile the code and run it.

Arduino issues with fsr and LCD

I am doing a project which requires the use of arduino uno, 4 force sensors and a 16x2 LCD. I'm trying to display the readings of the force sensors onto the LCD with the implementation of the buttons. For eg. if I press the up button it should display the first force sensor reading. The problem is it just displays a huge number of 143164976.0000 even when no force is applied on it. Please advice on whether there is a problem to my coding.
int iForceSensorReading; // the analog reading from the FSR resistor divider
int iForceSensorReading1;
int iForceSensorReading2;
int iForceSensorReading3;
int iForceSensorVoltage; // the analog reading converted to voltage
int iForceSensorVoltage1;
int iForceSensorVoltage2;
int iForceSensorVoltage3;
unsigned long ulForceSensorResistance;// The voltage converted to resistance, can be very big so make "long"
unsigned long ulForceSensorResistance1;
unsigned long ulForceSensorResistance2;
unsigned long ulForceSensorResistance3;
unsigned long ulForceSensorConductance;
unsigned long ulForceSensorConductance1;
unsigned long ulForceSensorConductance2;
unsigned long ulForceSensorConductance3;
float FsrForce = 0; // Finally, the resistance converted to force
float FsrForce1 = 0;
float FsrForce2 = 0;
float FsrForce3 = 0;
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7
void setup(void){
Serial.begin(9600); // send debugging information via the Serial monitor
lcd.begin(16, 2);
lcd.print("Hand Muscle");
lcd.setCursor(0,1);
lcd.print("Meter");
lcd.setBacklight(WHITE);
}
uint8_t i=0;
void loop(void){
uint8_t buttons = lcd.readButtons();
iForceSensorReading = analogRead(A0);//read index finger pressure
delay(30);
// analog voltage reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
iForceSensorVoltage = map(iForceSensorReading, 0, 1023, 0, 5000);
ulForceSensorConductance = conductanceFunction(ulForceSensorResistance, iForceSensorVoltage);
if (ulForceSensorConductance <= 1000){
FsrForce = ulForceSensorConductance / 80;
}
else{
FsrForce = ulForceSensorConductance - 1000;
FsrForce /= 30;
}
iForceSensorReading1 = analogRead(A1);//read middle finger pressure
delay(30);
iForceSensorVoltage1 = map(iForceSensorReading1, 0, 1023, 0, 5000);
if (iForceSensorVoltage1 == 0){
}
else{
ulForceSensorConductance1 = conductanceFunction(ulForceSensorResistance1, iForceSensorVoltage1);
delay(30);
}
if (ulForceSensorConductance1 <= 1000){
FsrForce1 = ulForceSensorConductance1 / 80;
}
else{
FsrForce1 = ulForceSensorConductance1 - 1000;
FsrForce1 /= 30;
}
iForceSensorReading2 = analogRead(A2);// read ring finger pressure
delay(30);
iForceSensorVoltage2 = map(iForceSensorReading2, 0, 1023, 0, 5000);
ulForceSensorConductance2 = conductanceFunction(ulForceSensorResistance2, iForceSensorVoltage2);
if (ulForceSensorConductance2 <= 1000){
FsrForce2 = ulForceSensorConductance2 / 80;
}
else{
FsrForce2 = ulForceSensorConductance2 - 1000;
FsrForce2 /= 30;
}
iForceSensorReading3 = analogRead(A3);//read little finger pressure
delay(30);
iForceSensorVoltage3 = map(iForceSensorReading3, 0, 1023, 0, 5000);
ulForceSensorConductance3 = conductanceFunction(ulForceSensorResistance3, iForceSensorVoltage3);
if (ulForceSensorConductance3 <= 1000)
{FsrForce3 = ulForceSensorConductance3 / 80;
}else
{FsrForce3 = ulForceSensorConductance3 - 1000;
FsrForce3 /= 30;
}
if (buttons) {
lcd.clear();
lcd.setCursor(0,0);
if (buttons & BUTTON_UP) {
lcd.print("Index Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_DOWN) {
lcd.print("Little Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce3,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_LEFT) {
lcd.print("Middle Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce1,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_RIGHT) {
lcd.print("Ring Finger: ");
lcd.setCursor(0,1);
lcd.print(FsrForce2,DEC);
lcd.setBacklight(WHITE);
}
if (buttons & BUTTON_SELECT) {
lcd.print("SELECT ");
lcd.setBacklight(WHITE);
}
}
}
// The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
// so FSR = ((Vcc - V) * R) / V
int conductanceFunction(long x, long y)
{long result;
x = 5000 - y; // fsrVoltage is in millivolts so 5V = 5000mV
x *= 10000; // 10K resistor
x /= y;
result = 1000000/x; //ulForceSensorConductance2 = 1000000 measured in micromhos
return result;
}
first likely issue, is this symptom sounds like a signed vs un-signed conflict. I see in your code the following calls
ulForceSensorConductance = conductanceFunction(ulForceSensorResistance, iForceSensorVoltage);
where
int conductanceFunction(long x, long y)
but
int iForceSensorVoltage;
You are passing an int(signed) into the second argument. Using it on math and creating a resultant variable of
long result;
and returning that as a INT.
Where you may have other problems.
You should follow some basic diagnostic procedures.
Assuming this problem is on ALL channels. if not then it is likely electrical.
Focusing on one channel.
PUT IN PRINTS of the various variables, to see what is moving as expected and validate the math is as expected

Resources