1

So I'm making a device that does 3 things,

  1. Measures frequency of an audio signal through a microphone
  2. 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)
  3. 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:

  1. 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
  2. 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;
  }
}
2
  • 1
    So post your combined code. You also need to combine the setup() functions and make sure you don't have any pin conflicts (hardware) or naming conflicts with your variable names (software)
    – Duncan C
    Jun 18, 2019 at 0:43
  • Sorry forgot the combined code, but to answer to rest of your post; I have done all of that and made sure it should run perfect, it seems to execute the frequency analysis perfectly but for some reason just doesn't want to do it with every cycle of doing pressure&temp.
    – collproj
    Jun 18, 2019 at 1:32

1 Answer 1

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 Ω.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.