Change state counter in 0-1 signal in Arduino

Hi, Maybe someone can help me. I have a binary signal and I want to have a counter which will be calculate a change state from 0 to 1 (only from 0 to 1) and will be displayed this information in serial monitor. The signal for example: 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0 (and correct result should be counter = 3) This is example signal but true signal will be infinite and generate every 1 second (every 1 second generate digit 0 or 1). Any example of code? Thanks a lot.

Any example of code?

What have you tried ?

You need to keep track of changes of state on the input See the StateChangeDetection example in the IDE

You will need to write non blocking code for the timing See Using millis() for timing. A beginners guide

I have a signal from sensor which give me values 0 or 1. The signal is still going unless I'm stop it (data incoming every 1 second). And every for example10 second (parameter) I want to know, how many times was change from 0 to 1 state. I'm a beginner so if is someone who can write the code I will be grateful.

I'm a beginner so if is someone who can write the code I will be grateful.

In this section of the forum the way it usually works is that you do your best to write the program and if you get stuck you post it here for help.

If you want the program to be written for you then you should ask the forum moderators to move the thread to the Gigs and Collaborations section of the forum but then you may have to pay someone to write the code.

OK, I understand. So know I prepare the code and maybe someone help me. It is similar what I want to do and the problem is how to get current and next value from the ‘myTable’.
I also know thah the ‘myTable’ cannot be used as a function as I did it.

int myTable[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}; // this is my signal
int i;
int counter; // to count the change state from 0 to 1

void setup() {
 Serial.begin(115200);
}

void loop() {
 for (i = 0; i < 15; i++) {
   if ((myTable(i) == 0) && (myTable(i+1) == 0)) {
     Serial.println("Next digit is the same");
   } else {
     Serial.println("Next digit is not the same");
     counter++;
   }
 }
 delay(1000);
}
      Serial.println("Next digit is not the same");
      counter++;

That does NOT meet the requirements that you spelled out earlier. You said you only wanted, for some strange reason, to count 1s that followed 0s.

Also, that statement is not true is myTable[ i ] and myTable[i+1] are both 0.

The array operator is , not ().

Where does myTable come from? This might be turning into an XY-problem.

Not a bad start but you are trying to access the array incorrectly

Try this

const byte myTable[] = {0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1}; // this is my signal
int counter; // to count the change state from 0 to 1

void setup()
{
  Serial.begin(115200);
  byte previousValue = myTable[0];
  for (int i = 0; i < 15; i++)  //deliberately compares level [0] with level [0]
  {
    byte currentValue = myTable[i];
    if ( currentValue == 1 && previousValue == 0)
    {
      counter++;
    }
    previousValue = currentValue;
  }
  Serial.print("Number of 0 to 1 transitions found : ");
  Serial.println(counter);
}

void loop()
{
}

Note that variables have been used for the previous and current values rather than merely using the values in the array ready for the changes that will be needed when the program has to use an incoming stream of data rather than an array as its source of data

Thanks UKHeliBob. This is exactly what I wanted to do. And learn :wink:
And know the most important: how I can compare incoming (every 1 second) data? My function is:

#include <MySignals.h>
#include "Wire.h"
#include "SPI.h" 


void setup() 
{
 Serial.begin(115200);
 MySignals.begin();
}


void loop() 
{

 float air = MySignals.getAirflow(VOLTAGE);   
 Serial.print("Airflow value :  ");
 Serial.print(air, 2);
 Serial.println(" V");
 
 delay(100); 
}

float air = MySignals.getAirflow(VOLTAGE); giving me a voltage value: 0, 0, 0, 1.8, 2, 2.4, 3, 2.2, 1,3, 0, 0, 0, 1.1, 1.7, 2.0… every 1 second. Sometimes I get value 0 so this is why I want to calculate change state only from 0 to another.

This airflow sensor is measure my breathing but not measuring how many times during 1 minute. So this is why I want to calculate changes from 0 to another during 1 minute in a loop because measure can take few minutes.

Now my code look like this (but it’s not working - it’s compiling but not working):

#include <MySignals.h>
#include "Wire.h"
#include "SPI.h" 

int counter;
int tempAir[1000];
int temp;
int dataLength = sizeof(tempAir);

void setup() 
{
 Serial.begin(115200);
 MySignals.begin();
}

void loop() 
{

 float air = MySignals.getAirflow(VOLTAGE);   

 byte previousValue = tempAir[0];
 for (int i = 0; i < dataLength; i ++)
 {
   byte currentValue = tempAir[i];
   if (currentValue > 0 && previousValue == 0)
   {
     counter++;
   }
   previousValue = currentValue;
 }

 
 Serial.print("Number of change state:  "); // after 1 minute
 Serial.println(counter);
 
 delay(1000); 
}

And after 60 second I would like to have an information about number of changes.

The first thing to do is to edit your post and put the code in code tags to stop parts of it turning into italics when an array index of [­i] is used

after 60 second I would like to have an information about number of changes.

Your requirements are not very clear. Do you want to count the number of 0 to 1 changes for 60 seconds then start counting again or do you want to count the number of 0 to 1 changes for the most recent 60 seconds ?

float air = MySignals.getAirflow(VOLTAGE); giving me a voltage value: 0, 0, 0, 1.8, 2, 2.4, 3, 2.2, 1,3, 0, 0, 0, 1.1, 1.7, 2.0.... every 1 second. Sometimes I get value 0 so this is why I want to calculate change state only from 0 to another.

Your introduction of the use of floats instead of integers also worries me. Can your guarantee a value of zero will occur or will the value be nearly zero but not quite ?

You do not need to store the values in an array. It would be more effective to just read the incoming value and compare it with the previous one. That is why I introduced the currentValue and previousValue variables in my example. That delay() will have to be eliminated too.

As I see it the code would work like this

initialise variables
start of loop()
  read the input
  if it has changed from 0 to 1
    add 1 to the counter
  end if
  if 60 seconds has elapsed (use millis() for timing)
    show the count
    reset variables  
  end if
end of loop()

Hello, I would like to count all changes during 60 seconds and displayed the information how many changes was during 60 seconds and again and again...(for example from 0 to 60 sec, next from 61 to 120 and again...).

So where are you stuck ?

You can read the current state. You know what the previous state was so can determine whether it has changed. Do not test the input for equality to zero if the number is a float, rather test whether it is below some low threshold.

Read the inputs for 60 seconds using millis() for non blocking timing. You can continuously look for changes of state and count them using this method

Your introduction of the use of floats instead of integers also worries me. Can your guarantee a value of zero will occur or will the value be nearly zero but not quite ?

Yes I 'm sure. I have float number and 0 (‘clear signal’ something or nothing).

Now my code is shown below:

#include <MySignals.h>
#include "Wire.h"
#include "SPI.h" 

int counter;
int tempAir[1000];
int temp;
int dataLength = sizeof(tempAir);
unsigned long time;

void setup() 
{
  Serial.begin(115200);
  MySignals.begin();
}

void loop() 
{

  float air = MySignals.getAirflow(VOLTAGE);   
  time = millis();
 
  byte previousValue = tempAir[0];
  for (int i = 0; i < dataLength; i ++)
  {
    byte currentValue = tempAir[i];
    if (currentValue > 0 && previousValue == 0) // greater than 0 because next value can be for example 0.5
    {
      counter++; // if was change from 0 to 1 state
    }
    previousValue = currentValue;
    
  }

    if (time == 60000) { // after 60 second display result
      Serial.print("Number of change state:  ");
      Serial.println(counter);
    }
     

  delay(1000); 
}

It is compiling without any errors, upload to arduino with sensor and in serial monitor I have nothink. No information about state change and I don’t know what is wrong. Maybe the problem is in my signal (in access to signal and analyzing it)?

Your code will not work for a number of reasons. Not least because you never save the value of air once you read it.

As I have said before, you do not need the array. You can count the transitions as they happen. Look at my pseudo code in reply #10

Try this

#include <MySignals.h>
#include "Wire.h"
#include "SPI.h"

int counter;

unsigned long startTime;
unsigned long currentTime;
unsigned long countPeriod = 6000;
boolean counting = false;
float currentValue;
float previousValue;

void setup()
{
  Serial.begin(115200);
  MySignals.begin();
}

void loop()
{
  currentTime = millis();   //get the current time each time through loop() for use later
  if (!counting)    //not currently counting so start again
  {
    startTime = currentTime;
    counting = true;
    counter = 0;
    previousValue = 0.0;
  }
  else
  {
    currentValue = MySignals.getAirflow(VOLTAGE); //I assume that this reads a value from the sensor
    if (currentValue != previousValue)  //if it has changed
    {
      if (currentValue > 0.1) //if it is greater than zero
      {
        counter++;    //count the transition
        Serial.println("Transition detected");
      }
    }
    if (currentTime - startTime >= countPeriod)   //if the timing period is over
    {
      Serial.print("Transitions in the period = "); //report the count
      Serial.println(counter);
      counting = false;   //reset the counting flag to start again
    }
  }
}

I have no way of testing it as I don’t have the library or associated hardware, nor can I compile it

int tempAir[1000];

Which Arduino are you using that has room in SRAM for 1000 ints?

I know that it is difficult to help without module. But I have some idea.
I’m use the ‘AnalogReadSerial’ built in example in Arduino. In the result I have the numbers displayed in serial monitor (this will be my signal). And now I want to check how many numbers is greater than 1 and displayed this information every 60 seconds.

unsigned long time;
int counter;
int tempArray[1000];
int dataLength = sizeof(tempArray);

void setup() {

  Serial.begin(9600); // initialize serial communication at 9600 bps
}

void loop() {

  int sensorValue = analogRead(A0); // read the input on analog pin 0

  Serial.println(sensorValue);      // print out the value you read
  time = millis();

  byte previousValue = tempArray[0];
  for (int i = 0; i < dataLength; i++)
  {
    byte currentValue = tempArray[i];
    if (currentValue > 0 && previousValue == 0)
    {
      counter++;
    }
    previousValue = currentValue;
  }
  if (time == 60000)
  {
    Serial.print("Numbers greater than 1: ");
    Serial.println(counter);
  }
  delay(1000);                      // delay in between reads for stability
}

This will help me to understand and will be somethink like sketch to do what I need.

PS: I know I stubbornly use the array, but I do not know how else. Sorry :wink:

You are reading the sensor value then ignoring it. If you insist on using an array, assuming that you have enough memory, then at least save the values to it for before testing them at the end of the period. Note that the array must be declared with the correct data type as must both the current and previous values.

Did you try my code ? Does it compile ? What happens when you run it ?

PS: I know I stubbornly use the array, but I do not know how else. Sorry

And you stubbornly won't tell us which Arduino you are using.

  if (time == 60000)

What are the odds of millis() returning EXACTLY 60000?

I have solved my problem and now my module works as I want. Thanks all, especially UKHeliBob for help.