31 Counts in percents? & continues counts...

I'm curious why there is no Serial.begin() statement in setup() and no Serial.print() statements in loop(). It almost seems like you don't want to learn to debug your own program.

Your switch reading code is far too complicated. First, you need to look at the State Change Detection example, to see how to detect a transition from not pressed to pressed.

Once you detect that there is a switch press, you diddle around reading some stuff, and writing to the LCD AND you have a 5 second delay. There isn't a switch on earth that bounces that long, so your complicated debouncing code is useless.

PaulS:
I'm curious why there is no Serial.begin() statement in setup() and no Serial.print() statements in loop(). It almost seems like you don't want to learn to debug your own program.

Your switch reading code is far too complicated. First, you need to look at the State Change Detection example, to see how to detect a transition from not pressed to pressed.

Once you detect that there is a switch press, you diddle around reading some stuff, and writing to the LCD AND you have a 5 second delay. There isn't a switch on earth that bounces that long, so your complicated debouncing code is useless.

I have no use for serial printing.... but how can i debug using it?
I honestly dont know why i have to use the debounce-code, the button (all my other buttons to) are working fine without debounce.

I honestly dont know why i have to use the debounce-code, the button (all my other buttons to) are working fine without debounce.

As I said, you probably don't need to worry about it.

            count = count += 1;

Well, that's novel. That is equivalent to:

count = count = count + 1;

I have no use for serial printing...

Well, I find it essential for debugging, but, to each his own. Good luck.

PaulS:

I honestly dont know why i have to use the debounce-code, the button (all my other buttons to) are working fine without debounce.

As I said, you probably don't need to worry about it.

            count = count += 1;

Well, that's novel. That is equivalent to:

count = count = count + 1;

I have no use for serial printing...

Well, I find it essential for debugging, but, to each his own. Good luck.

By that i ment that i am not gonna connect the device to the computer... :slight_smile: when debugging... is there any type of command line for that or do i set a couple of serial.print's?

This code actually works fine, except it displays the count starting at 11, not 1 :confused:

#include <FreqMeasure.h>
#include <Math.h>
#include <LiquidCrystal.h>

float Msqm;
const float A = 22.0;
int buttonSQM = A2; 
int val = 0;
int reading = 0;
LiquidCrystal lcd (12, 11, 10, 9, 7, 6);


void setup() {
   FreqMeasure.begin();
   pinMode(buttonSQM, INPUT_PULLUP);
   digitalWrite(buttonSQM, HIGH);
   lcd.begin(16,2);
}

double sum=0;
int count=0;

void loop() {
  val = digitalRead(buttonSQM);
   if (val == LOW) {
      reading = 1;                       
      while(reading) {                     
         if (FreqMeasure.available()) {
            // average several reading together
            sum = sum + FreqMeasure.read();
            count +=1;
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Reading");
            lcd.setCursor(8,0);
            lcd.print(count);
            if (count > 30) {
               double frequency = F_CPU / (sum / count);
               sum = 0;
               count = 0;
               
               Msqm = A - 2.5*log10(frequency); //Egen Kod
               lcd.clear();
               lcd.setCursor(0,0);
               lcd.println("Mag/AS2:");
               lcd.setCursor(8,0);
               lcd.print(Msqm);
               delay(5000);
               lcd.clear();
               reading = 0;                   
            }
         }
      }
   }
}

By that i ment that i am not gonna connect the device to the computer... smiley when debugging... is there any type of command line for that or do i set a couple of serial.print's?

If you are not going to connect the Arduino to the PC, then it doesn't matter. You can't (effectively) use Serial.begin() or Serial.print() if there is nothing on the other end of the serial port.

This code actually works fine, except it displays the count starting at 11, not 1 :confused:

I'm wondering if that is an LCD issue, rather than a count issue. That's why I like Serial.print() better. You can put markers on either side of the value, to confirm that the value is 1 rather than 11, or the other way around.

PaulS:

By that i ment that i am not gonna connect the device to the computer... smiley when debugging... is there any type of command line for that or do i set a couple of serial.print's?

If you are not going to connect the Arduino to the PC, then it doesn't matter. You can't (effectively) use Serial.begin() or Serial.print() if there is nothing on the other end of the serial port.

This code actually works fine, except it displays the count starting at 11, not 1 :confused:

I'm wondering if that is an LCD issue, rather than a count issue. That's why I like Serial.print() better. You can put markers on either side of the value, to confirm that the value is 1 rather than 11, or the other way around.

Hmm... maybee it is... but i have lcd.clear before, shouldn´t that "take care" of it? or is it time for a sprintf?

The only way your going to know for sure is if you use the serial monitor.

I add the Serial.Print and now see the benefits of having one even when ia don´t "need it" :roll_eyes:

It actually counts from 1-31 every time... but after the first time i press the button it counts 1.....2.....3... ...31 with about 1 sec between every count, it display the result as it should and then clear the display... the next time i press the button, it counts up from 1 to 11 in a fraction of a second, and starts the regular count from 11-31 with about 1 sec between every count... i have no clue what that can be :confused:

I guess that the first time you press the button you have fresh data from FreqMeasure; not enough time to buffer them, so the timing is dictated by how frequently FreqMeasure.available() is not zero. But during the 5 seconds delay() some data are buffered, probably enough for the first 10 samples.

But it doesn´t matter if i wait those 5 sec or three minutes, it still begins at 11.... i think its strange :wink:

I have also began to write a formula to display the progress in percentage with the formula below, however, it returns 0% during the whole measurements until its finished counting the 31 pulses, then it display 100%... any idea?

int percentage = 0;

percentage = count/31*100;
            Serial.print("Counts:  ");
            Serial.print(count); 
            Serial.print("Progress");           
            Serial.print(percentage);
            Serial.println("%");

BR/ Daniel

EDIT:, i found on the "freqmeasure" website that a command that is called FreqMeasure.end(); might be useful... maybe this solves my problem?

http://www.pjrc.com/teensy/td_libs_FreqMeasure.html

No. I mean, after a FreqMeasure.end() you would have to call FreqMeasure.begin() again.

To understand the "start from 11" behavior one should start from FreqMeasure.cpp:

#define FREQMEASURE_BUFFER_LEN 12
static volatile uint32_t buffer_value[FREQMEASURE_BUFFER_LEN];

This suggests that no more than 12 samples can be kept in the buffer. After filling the buffer the code will wait until space is available again (i.e. the buffer has been transmitted and read). That's why you can wait 5 seconds or 5 minutes and get the same results. The only issue is why the program doesn't begin at 12, but I'll leave it for another time.

In your code, you should consider what happens when you divide two integers and assign the result to an integer. The result will be truncated (3/2=1, and 2/3=0). And, count/31100 will translate into 0100=0. This is why in the library examples they use a double.

[edit] Of course, if you want to call end() and then begin() again I'm not going to stop you, but you'll have to change your loop accordingly, keeping track of the state of FreqMeasure. I forgot to mention the possible alternative, i.e. emptying the buffer by repeatedly reading it, until available() returns 0, and throwing away the results.

Try to move this outside the IF statement. "double frequency = F_CPU / (sum / count);"

spatula:
No. I mean, after a FreqMeasure.end() you would have to call FreqMeasure.begin() again.

To understand the "start from 11" behavior one should start from FreqMeasure.cpp:

#define FREQMEASURE_BUFFER_LEN 12

static volatile uint32_t buffer_value[FREQMEASURE_BUFFER_LEN];




This suggests that no more than 12 samples can be kept in the buffer. After filling the buffer the code will wait until space is available again (i.e. the buffer has been transmitted and read). That's why you can wait 5 seconds or 5 minutes and get the same results. The only issue is why the program doesn't begin at 12, but I'll leave it for another time.

In your code, you should consider what happens when you divide two integers and assign the result to an integer. The result will be truncated (3/2=1, and 2/3=0). And, count/31*100 will translate into 0*100=0. This is why in the library examples they use a double.

This is spot on, it all makes very much sense now...

Ok, so if i set persentage as a double it would be better? i am not good at all regarding formulas...

HazardsMind:
Try to move this outside the IF statement. "double frequency = F_CPU / (sum / count);"

Why should i do that? :blush:

You want the frequency to increase as the count increases right? Well the only time you will see the frequency is when count > 31, so by taking it out of that IF statement, it will do just that.

Edit: oh

Nope, i want to measure the pulses 30 times and then take the avarage of them to increase accuracy :slight_smile:

Corpze:
Ok, so if i set persentage as a double it would be better? i am not good at all regarding formulas...

Since you don't need a high precision you can use a float.

float percent = (float)count/31.0*100.0;

This statement casts count to (be treated as a) float, then both 100 and 31 are made floats by adding the decimal 0.

Also note that I edited my previous post on how to address the problem of overflow.
When you print percent you can use print(percent, n) where n is the desired precision, if any.

spatula:

Corpze:
Ok, so if i set persentage as a double it would be better? i am not good at all regarding formulas...

Since you don't need a high precision you can use a float.

float percent = (float)count/31.0*100.0;

This statement casts count to (be treated as a) float, then both 100 and 31 are made floats by adding the decimal 0.

Also note that I edited my previous post on how to address the problem of overflow.
When you print percent you can use print(percent, n) where n is the desired precision, if any.

No i don´t need any precision at all regarding the percentage, it´s just me wanting a little bit more nice progress-status than counting to 31 :wink:
I think the FreqMeasure begin and FreqMeasure end will suit me just fine if that works as i think they do, i want to point my sensor at a given part of the sky, than initiate the reading, print the result and if i want to, take another reading, if the freqMeasure library holds 12 measurements from my sensor in it´s buffer, those readings might be from when my sensor is pointed down at the ground or something like that :~

This is how the code looks like for now:

#include <FreqMeasure.h>
#include <Math.h>
#include <LiquidCrystal.h>

float Msqm;
const float A = 22.0;
int buttonSQM = A2; 
int val = 0;
int reading = 0;
float percentage = 0;
LiquidCrystal lcd (12, 11, 10, 9, 7, 6);


void setup() {
   
   pinMode(buttonSQM, INPUT_PULLUP);
   digitalWrite(buttonSQM, HIGH);
   lcd.begin(16,2);
   Serial.begin(19200);
}

double sum=0;
int count=0;

void loop() {
  val = digitalRead(buttonSQM);
   if (val == LOW) {
      reading = 1;                       
      while(reading) {
         FreqMeasure.begin();        
         if (FreqMeasure.available()) {
            // average several reading together
            sum = sum + FreqMeasure.read();
            count +=1;
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Reading");
            lcd.setCursor(8,0);
            lcd.print(count);
            
            float percent = (float)count/31.0*100.0;

            Serial.print("Counts:  ");
            Serial.print(count); 
            Serial.print("Progress");           
            Serial.print(percentage);
            Serial.println("%");
            
            if (count > 30) {
               double frequency = F_CPU / (sum / count);
               sum = 0;
               count = 0;
               
               Msqm = A - 2.5*log10(frequency); //Frequency to magnitudes/arcSecond2 formula
               FreqMeasure.end(); 
               lcd.clear();
               lcd.setCursor(0,0);
               lcd.println("Mag/As2:");
               lcd.setCursor(8,0);
               lcd.print(Msqm);
               delay(5000);
               lcd.clear();
               reading = 0;                   
            }
         }
      }
   }
}

Ok, so if i set persentage as a double it would be better?

Since you don't need a high precision you can use a float.

Psst, spatula, floats and doubles are the same size on the Arduino.

Ok, got everything to work exactly as i want to now :slight_smile:

This is what the serial monitor shows now:

Counts: 1 Progress: 3%
Counts: 2 Progress: 6%
Counts: 3 Progress: 9%
Counts: 4 Progress: 12%
Counts: 5 Progress: 16%
Counts: 6 Progress: 19%
Counts: 7 Progress: 22%
Counts: 8 Progress: 25%
Counts: 9 Progress: 29%
Counts: 10 Progress: 32%
Counts: 11 Progress: 35%
Counts: 12 Progress: 38%
Counts: 13 Progress: 41%
Counts: 14 Progress: 45%
Counts: 15 Progress: 48%
Counts: 16 Progress: 51%
Counts: 17 Progress: 54%
Counts: 18 Progress: 58%
Counts: 19 Progress: 61%
Counts: 20 Progress: 64%
Counts: 21 Progress: 67%
Counts: 22 Progress: 70%
Counts: 23 Progress: 74%
Counts: 24 Progress: 77%
Counts: 25 Progress: 80%
Counts: 26 Progress: 83%
Counts: 27 Progress: 87%
Counts: 28 Progress: 90%
Counts: 29 Progress: 93%
Counts: 30 Progress: 96%
Counts: 31 Progress: 100%
22.35

And this is the code, as you can see i was able to use the FreqMeasure.end, it stops taking measurements until i press the button again, and it holds no measurements at all in the buffer. It prints nice to the LCD to! I also changed the percentage to an int because i don´t need that accuracy, that makes the "CPU" work a little easier huh? :stuck_out_tongue:

Thanks for all the help you guys! Couldnt have done it without you!

#include <FreqMeasure.h>
#include <Math.h>
#include <LiquidCrystal.h>

float Msqm;
const float A = 22.0;
int buttonSQM = A2; 
int val = 0;
int reading = 0;
int percentage = 0;
LiquidCrystal lcd (12, 11, 10, 9, 7, 6);


void setup() {
   
   pinMode(buttonSQM, INPUT_PULLUP);
   digitalWrite(buttonSQM, HIGH);
   lcd.begin(16,2);
   Serial.begin(19200);
}

double sum=0;
int count=0;

void loop() {
  val = digitalRead(buttonSQM);
   if (val == LOW) {
      reading = 1;
      FreqMeasure.begin();      
      while(reading) {
                 
         if (FreqMeasure.available()) {
            // average several reading together
            sum = sum + FreqMeasure.read();
            count +=1;
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Reading");
            lcd.setCursor(8,0);
            lcd.print(percentage);
            lcd.setCursor(11,0);
            lcd.print("%");
            
            percentage = count/31.0*100.0;

            Serial.print("Counts: ");
            Serial.print(count); 
            Serial.print(" Progress: ");           
            Serial.print(percentage);
            Serial.println("%");
            
            
            if (count > 30) {
               double frequency = F_CPU / (sum / count);
               sum = 0;
               count = 0;
               
               Msqm = A - 2.5*log10(frequency); //Frequency to magnitudes/arcSecond2 formula
                
               lcd.clear();
               lcd.setCursor(0,0);
               lcd.println("Mag/As2: ");
               lcd.setCursor(9,0);
               lcd.print(Msqm);
               Serial.print(Msqm);
               delay(5000);
               lcd.clear();
               reading = 0; 
               FreqMeasure.end();
            }
         }
      }
   }
}

Thats great! It's also strange that a simple function like not having FreqMeasure.end() could do so much. Well, it's a learning experience, and you figured it out.

Very good.