Hello! this is my first time posting, and I have searched everywhere I could on this forum before posting, as I want to respect the time and instructions of the volunteers on here. Long story short, I have developed a serious night time teeth grinding condition that has damaged my jaw joints, and I am trying to build a deviIce that uses an Arduino Uno 4th Generation, a Myoware muscle sensor (provides an analog signal), and a piezo buzzer to notify me via noise feedback to wake me up if I cross a clenching threshold.
I have located the myoware code and it appears fairly straight forward for a rookie like me, I was hoping one of the experts on the forum would be able to review my code to see if it makes sense? I've basically combined the myoware code with piezo buzzer threshold code, so hopefully I'm on the right track below.
Under normal circumstances I'd spend months learning / validating my code, but I'm pretty desperate to get my device working as the pain I'm living with is terrible, I wouldn't wish a Temporomandibular disorder on my worst enemy!
Thank you in advance, this forum is a fantastic resource and I'm very thankful for the volunteers on here.
Cal
// the setup routine runs once when you press reset:
// constants won't change
const int SENSOR_PIN = A0; // Arduino pin connected to SENSOR pin
const int BUZZER_PIN = 3; // Arduino pin connected to Buzzer's pin
const int ANALOG_THRESHOLD = 500;
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(BUZZER_PIN, OUTPUT); // set arduino pin to output mode;
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
delay(1); // delay in between reads for stability
int sensorValue = analogRead(SENSOR_PIN); // read the input on analog pin
if(sensorValue > ANALOG_THRESHOLD)
digitalWrite(BUZZER_PIN, HIGH); // turn on Piezo Buzzer
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
}
I would guess your console is getting a lot of data very fast. Try slowing down your loop, (bad word) with a delay(2000). This will give you a chance to see what is happening.
That is great input thanks, I will try a few different delays to see what works best, I suspect because of my clenching, the values will remain above my threshold for some extended periods of time, so I should be able to increase the delay a bit. What would be the downside of a loop of 1 with respect to making the buzzer work?
Other than the delay suggestion, does my code look like it will work once I upload it to my Arduino? I receive a few parts for the circuit today, so I will be able to assemble it soon, I just wanted to verify my code looks good in theory.
Your code will not work if you upload it to a Uno.
Consider this code you wrote:
if(sensorValue > ANALOG_THRESHOLD)
digitalWrite(BUZZER_PIN, HIGH); // turn on Piezo Buzzer
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
against the syntax of a c++ if statement
if (condition1) {
// block of code to be executed if condition1 is true
} else if (condition2) {
// block of code to be executed if the condition1 is false and condition2 is true
} else {
// block of code to be executed if the condition1 is false and condition2 is false
}
The code should work once you get rid of the double definition of sensorValue but only IF you have bought an active buzzer and the not the more common passive buzzer. A passive buzzer needs tone() and notone() instead of just digitalWrites.
Note: the if/else is fine because you have only single commands. The {} are only needed for blocks of code, i.e. multiple commands.
Possibly the sensor works in a way that the buzzer is switched on and off too fast. Maybe it helps to just let it buzz for 5 seconds the moment the threshold is passed:
if(sensorValue > ANALOG_THRESHOLD) {
digitalWrite(BUZZER_PIN, HIGH); // turn on Piezo Buzzer
delay(5000); // and keep it on for 5 seconds before doing the next sensor reading.
}
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
In case you need to output a tone, use:
if(sensorValue > ANALOG_THRESHOLD) {
tone(BUZZER_PIN, 1000); // turn on Piezo Buzzer - 1000 Hz
delay(5000); // and keep it on for 5 seconds before doing the next sensor reading.
noTone(BUZZER_PIN)
}
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
I tested the device today now that I have the myoware sensor headers soldered up and all connections made - so far so good! For today's test I placed the EMG probes on my masseter muscle since it puts out a nice distinct signal, it appears anything above 100 units would be a good threshold, so I adjusted the code accordingly.
I also hooked up a passive piezo buzzer to pin 3 with one wire, and ground for the other wire. When the sensor output hits 100 units, I get a quiet little "tick" sound, which does prove that the code is working, but won't wake me up.
I am starting to see that I'll need to be a bit more descriptive in my code as I need a sustained audible beeeeeeep. It would also be ideal for the threshold to be a bit more "patient" as there are occasions where the sensor will pick up a bit of noise and send a nuisance 100+ value even if I am not clenching.
thanks again for all your support, today was very encouraging as it looks like we are on the right track. if you have any coding suggestions for a more sustained audible beep, and a for a more selective threshold that would be awsome. If we can succeed with this device I'll post it on youtube and elsewhere because I know there is an epidemic of teeth grinding and TMJ disorders on the horizon with this pandemic, and I think this device could really help people.
Here is my code that needs adjusting:
/*
AnalogReadSerial
Reads an analog input on pin 0, prints the result to the Serial Monitor.
Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/AnalogReadSerial
*/
// the setup routine runs once when you press reset:
// constants won't change
const int SENSOR_PIN = A0; // Arduino pin connected to SENSOR pin
const int BUZZER_PIN = 3; // Arduino pin connected to Buzzer's pin
const int ANALOG_THRESHOLD = 100;
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(BUZZER_PIN, OUTPUT); // set arduino pin to output mode;
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue);
delay(1); // delay in between reads for stability
if(sensorValue > ANALOG_THRESHOLD) {
digitalWrite(BUZZER_PIN, HIGH); // turn on Piezo Buzzer
delay(5000); // and keep it on for 5 seconds before doing the next sensor reading.
}
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
}
I am using an Arduino R3, would that work with the Simple Kalman Filter? I've attempted to integrate the code you linked to above, but I seem to be getting an error 'simpleKalmanFilter' was not declared in this scope:
I also made an adjustment from my previous code to state that < int sensorValue = float estimated value > since my thinking was that we no longer want sensor value to be from Pin A0, we want it to be the the estimated value from the filter - hopefully my line of thinking is correct?
I also added these lines below the const lines
const long SERIAL_REFRESH_TIME = 100; // Serial output refresh time
long refresh_time;
Other than the filter coding, I am also still curious how to make my piezo buzzer stay on for a few seconds once it reads the newly filtered input data.
Here is my code so far - thanks again for the help
/*
AnalogReadSerial
Reads an analog input on pin 0, prints the result to the Serial Monitor.
Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/AnalogReadSerial
*/
// the setup routine runs once when you press reset:
// constants won't change
const int SENSOR_PIN = A0; // Arduino pin connected to SENSOR pin
const int BUZZER_PIN = 3; // Arduino pin connected to Buzzer's pin
const int ANALOG_THRESHOLD = 100;
const long SERIAL_REFRESH_TIME = 100; // Serial output refresh time
long refresh_time;
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(BUZZER_PIN, OUTPUT); // set arduino pin to output mode;
}
// the loop routine runs over and over again forever:
void loop() {
// read a reference value from A0 and map it from 0 to 100
float real_value = analogRead(A0)/1024.0 * 100.0;
// add a noise to the reference value and use as the measured value
float measured_value = real_value + random(-100,100)/100.0;
// calculate the estimated value with Kalman Filter
float estimated_value = simpleKalmanFilter.updateEstimate(measured_value);
// send to Serial output every 100ms
// use the Serial Ploter for a good visualization
if (millis() > refresh_time) {
Serial.print(real_value,4);
Serial.print(",");
Serial.print(measured_value,4);
Serial.print(",");
Serial.print(estimated_value,4);
Serial.println();
refresh_time = millis() + SERIAL_REFRESH_TIME;
// read the input from float estimated.value:
int sensorValue = float estimated_value);
// print out the value you read:
Serial.println(sensorValue);
delay(1); // delay in between reads for stability
if(sensorValue > ANALOG_THRESHOLD) {
digitalWrite(BUZZER_PIN, HIGH); // turn on Piezo Buzzer
delay(5000); // and keep it on for 5 seconds before doing the next sensor reading.
}
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
}
Quick update! I did as a few forum members suggested and I am now getting an audible tone! I used this code with a passive piezo buzzer:
So as stated in my previous post, I need to find a way to get the filtering code to work.
if(sensorValue > ANALOG_THRESHOLD) {
tone(BUZZER_PIN, 1000); // turn on Piezo Buzzer - 1000 Hz
delay(1000); // and keep it on for 5 seconds before doing the next sensor reading.
noTone(BUZZER_PIN);
}
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
Any ideas of how to fix the following error below for my Kalman filter code? I'm getting an error on the line indicated below, and the error reads:
"SimpleKalmanFilter" was not declared in scope ?
/*
AnalogReadSerial
Reads an analog input on pin 0, prints the result to the Serial Monitor.
Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/AnalogReadSerial
*/
// the setup routine runs once when you press reset:
// constants won't change
const int SENSOR_PIN = A0; // Arduino pin connected to SENSOR pin
const int BUZZER_PIN = 3; // Arduino pin connected to Buzzer's pin
const int ANALOG_THRESHOLD = 100;
const long SERIAL_REFRESH_TIME = 100; // Serial output refresh time
long refresh_time;
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(BUZZER_PIN, OUTPUT); // set arduino pin to output mode;
}
// the loop routine runs over and over again forever:
void loop() {
// read a reference value from A0 and map it from 0 to 100
float real_value = analogRead(A0)/1024.0 * 100.0;
// add a noise to the reference value and use as the measured value
float measured_value = real_value + random(-100,100)/100.0;
// calculate the estimated value with Kalman Filter
float estimated_value = simpleKalmanFilter.updateEstimate(measured_value); *** ERROR ON THIS LINE***
// send to Serial output every 100ms
// use the Serial Ploter for a good visualization
if (millis() > refresh_time) {
Serial.print(real_value,4);
Serial.print(",");
Serial.print(measured_value,4);
Serial.print(",");
Serial.print(estimated_value,4);
Serial.println();
refresh_time = millis() + SERIAL_REFRESH_TIME;
// read the input on analog pin 0:
int sensorValue = float estimated_value);
// print out the value you read:
Serial.println(sensorValue);
delay(1); // delay in between reads for stability
if(sensorValue > ANALOG_THRESHOLD) {
digitalWrite(BUZZER_PIN, HIGH); // turn on Piezo Buzzer
delay(5000); // and keep it on for 5 seconds before doing the next sensor reading.
}
else
digitalWrite(BUZZER_PIN, LOW); // turn off Piezo Buzzer
}