So I'm making a device that does 3 things,
- Measures frequency of an audio signal through a microphone
- Checks whether there is a weight placed on a pressure pad (my pressure sensor works through the resistance of the material changing when a weight is placed on it)
- Measure ambient room temperature
I have coded each individual section and tested them individually to find them work great, here are the sketches.
Frequency sketch :
// runs every time thru the loop
setInputState();
// count every transision HIGH<->LOW
if (inputState != lastInputState) {
count++;
lastInputState = inputState;
}
if (millis() - previousCountMillis >= countMillis) {
previousCountMillis += countMillis;
// show Hz on Serial too if available
Serial.print(count);
Serial.println(" Hz");
ledtest = count;
// reset to zero for the next half second's sample
count = 0L;
}
if (ledtest >= 400 && ledtest <= 850){
digitalWrite(A2, HIGH);
}
else if (ledtest < 400 || ledtest > 850){
digitalWrite(A2, LOW);
}
}
Here is the pressure sensor sketch
int Vin = 5;
float Vout = 0;
float raw1 = 0;
int R1 = 770;
int R2old1 = 0;
int R2new1 = 0;
int R2avg1 = 0;
int pressurelog = 0;
void setup() {
pinMode(A0, INPUT); //Receive pressure voltage
pinMode(A1, OUTPUT); //Red led, PRESSURE PAD
}
void loop() {
raw1 = analogRead(A0);
Vout = raw1*5/1024;
R2old1 = Vout*R1/(Vin-Vout);
raw1 = analogRead(A0);
Vout = raw1*5/1024;
R2new1 = Vout*R1/(Vin-Vout);
R2avg1 = (R2new1+R2old1)/2;
Serial.print("Resistance: ");
Serial.println(R2avg1);
if (R2avg1 >= 1000){
digitalWrite(A1, LOW);
pressurelog = 0;
}
else if (R2avg1 <= 1000){
digitalWrite(A1, HIGH);
pressurelog = 1;
}
}
here is the temperature code
float raw = 0;
float tempC = 0;
float tempF = 0;
void setup() {
pinMode(A5, INPUT);
pinMode(A1, OUTPUT);
Serial.begin(9600);
}
void loop() {
raw = analogRead(A5) * 0.004882814;
tempC = (raw - 0.5) * 100.0;
tempF = (180.0/100.0)*tempC + 32.0;
Serial.print("temp: ");
Serial.println(tempF);
delay(1000);
}
I coupled the "void loop" of all three and defined everything and ran the code to give a peculiar output. It does the temp and pressure reporting just fine but seems to constantly skip the frequency measurement. It seems to like doing the pressure and temperature measurement like 50 times then do an audio measurement which doesn't make sense as it should do it sequentially.
I TRIED:
- adding a delay between the frequency measurement and the other two. This didn't work as now the audio measurement work, as it relies on the millis () function
- adding the 3 components in 3 different functions and calling them sequentially. This results in the exact same stupid output.
Does anyone have an idea or solution?
Combined code:
int Vin = 5;
float Vout = 0;
float raw1 = 0;
int R1 = 770;
int R2old1 = 0;
int R2new1 = 0;
int R2avg1 = 0;
int pressurelog = 0;
const byte inputPin = 2;
boolean inputState = false;
boolean lastInputState = false;
long count = 0L;
int ledtest = 0L;
unsigned long previousCountMillis = millis();
const long countMillis = 500L;
void setInputState() {
inputState = digitalRead(inputPin);
}
int crylog = 0;
float raw = 0;
float tempC = 0;
float tempF = 0;
int templog = 0;
void setup() {
pinMode(inputPin, INPUT); //Receive microphone data
pinMode(A0, INPUT); //Receive pressure voltage
pinMode(A1, OUTPUT); //Red led, PRESSURE PAD
pinMode(A2, OUTPUT); //Blue led, FREQUENCY/CRYING
pinMode(A3, OUTPUT); //Green led, TEMPERATURE
pinMode(A4, OUTPUT); //Red led, MAX WARNING
Serial.begin(115200);
}
void loop() {
Serial.println("HI");
Cryometer();
delay(2);
Serial.println("YO");
Pressure();
Temperature();
// WARNING SETUP
if (pressurelog == 1 && templog == 1){
digitalWrite(A4, HIGH);
}
else {
digitalWrite(A4, LOW);
}
}
void Pressure() {
raw1 = analogRead(A0);
Vout = raw1*5/1024;
R2old1 = Vout*R1/(Vin-Vout);
raw1 = analogRead(A0);
Vout = raw1*5/1024;
R2new1 = Vout*R1/(Vin-Vout);
R2avg1 = (R2new1+R2old1)/2;
Serial.print("Resistance: ");
Serial.println(R2avg1);
if (R2avg1 >= 1000){
digitalWrite(A1, LOW);
pressurelog = 0;
}
else if (R2avg1 <= 1000){
digitalWrite(A1, HIGH);
pressurelog = 1;
}
}
void Cryometer(){
// runs every time thru the loop
setInputState();
// count every transision HIGH<->LOW
if (inputState != lastInputState) {
count++;
lastInputState = inputState;
}
if (millis() - previousCountMillis >= countMillis) {
previousCountMillis += countMillis;
// show Hz on Serial too if available
Serial.print("Frequency: ");
Serial.print(count);
Serial.println(" Hz");
ledtest = count;
// reset to zero for the next half second's sample
count = 0L;
}
if (ledtest >= 400 && ledtest <= 850){
digitalWrite(A2, HIGH);
crylog = 1;
}
else if (ledtest < 400 || ledtest > 850){
digitalWrite(A2, LOW);
crylog = 0;
}
}
void Temperature() {
raw = analogRead(A5) * 0.004882814;
tempC = (raw - 0.5) * 100.0;
tempF = (180.0/100.0)*tempC + 32.0;
Serial.print("Temperature (F): ");
Serial.println(tempF);
Serial.println();
if (tempF >= 75 && ledtest <= 50){
digitalWrite(A3, HIGH);
templog = 1;
}
else if (ledtest < 50 || ledtest > 75){
digitalWrite(A3, LOW);
templog = 0;
}
}
1 Answer 1
Your approach is globally sound. However, the code that measures the input frequency is very time sensitive. Thus, you have to make sure this piece of code is never delayed by anything else. This means that everything in your sketch should be fast and non-blocking.
I see a few instances of blocking behaviour you should get rid of: the
call to delay()
and the serial prints. The first is particularly
useless, so just remove it. Printing to the serial port is fine as long
as you do not try to print too much. If you try to print at every loop
iteration, you end up filling the output buffer. From there on every
print becomes a blocking call: the serial library has to wait for the
port to send out the data, until there is enough room in the buffer for
what you want to send. The solution is to throttle down the output rate
by only printing once in a while. You have done this brilliantly in the
frequency-meter code:
if (millis() - previousCountMillis >= countMillis) {
previousCountMillis += countMillis;
Serial.print("Frequency: ");
Serial.print(count);
Serial.println(" Hz");
// ...
}
Now you just have to apply the same technique to every instance of
Serial.print()
and Serial.println()
. Well, maybe the "HI" "YO" could
just be removed instead...
Once you remove these blocking behaviors from your sketch, it will
probably run fast enough for the frequency counting to perform
correctly. There is still something you may want to optimize though: the
computations in Pressure()
are horribly inefficient, especially
considering that you have an 8-bit CPU with no hardware floating point
support. If you need to average, I suggest you average the analog
readings rather than computed resistances. Also note that computing the
voltage at the analog pin is completely useless:
void Pressure() {
int raw = analogRead(A0) + analogRead(A0);
float R = (float) R1 * raw / (2048 - raw);
// ...
}
You may even replace float
by long
if you don't need a resolution
better than 1 Ω.
Explore related questions
See similar questions with these tags.
setup()
functions and make sure you don't have any pin conflicts (hardware) or naming conflicts with your variable names (software)