Object counter « counting box »

Hi,

Quick message to tell you that i’ll be on holiday until end of this week. So nothing will happen on that project :slight_smile:

Thank you,

Hi,

I'm proud to announced that the project seems to work pretty good ! See picture attached.
I corrected some pieces of code (still not changed it with the boolean variables).

I have 1 mini-issue : when i start the arduino, the variable FC51 always goes to 1 by itself, so the counter starts at 1. When i press reset, it goes to 0 and everything becomes normal.
Do you know why the FC51 reacts like that ? Is there a workaround that it doesn't, or at least that the counter really starts at 0 and not 1 ? Maybe something to change in the code ?

Below the current code :

#include "LedControl.h"
LedControl lc = LedControl(4,5,6,4);

// ----- Code for Change State for FC-51
// this constant won't change:
const int  PinFC51 = 12;    // the pin that the pushbutton is attached to
const int  PinButtonPlus1 = 8;    // the pin that the pushbutton is attached to
const int  PinButtonMinus1 = 9;    // the pin that the pushbutton is attached to
const int  PinButtonReset = 10;    // the pin that the pushbutton is attached to
const int PinLED = 4;       // the pin that the LED is attached to

// Variables will change:
int buttonStateFC51 = 0;         // current state of the FC51
int lastButtonStateFC51 = 0;     // previous state of the FC51

int buttonStatePlus1 = 0;         // current state of the button
int lastButtonStatePlus1 = 0;     // previous state of the button

int buttonStateMinus1 = 0;         // current state of the button
int lastButtonStateMinus1 = 0;     // previous state of the button

int buttonStateReset = 0;         // current state of the button
int lastButtonStateReset = 0;     // previous state of the button


int FC51 = 0;
int ButtonPlus1 = 0;
int ButtonMinus1 = 0;
int ButtonReset = 0;


// ----- Code for Max7219 + LEDs
int count = 0;


void setup()
{

// ----- Code for Change State for FC-51
  // initialize the button pin as an input:
  pinMode(PinFC51, INPUT);
  pinMode(PinButtonPlus1, INPUT);
  pinMode(PinButtonMinus1, INPUT);
  pinMode(PinButtonReset, INPUT);
  
  // initialize the LED as an output:
  pinMode(PinLED, OUTPUT);
  
  // initialize serial communication:
  Serial.begin(9600);

// ----- Code for Max7219 + LEDs
    lc.shutdown(0,false); //to activate the led's
    lc.setIntensity(0,5); //to define the brightness of the led's
    lc.clearDisplay(0); //to cancel all info on the led's
    lc.setDigit(0,0,0,false); //to show 0 as initial number - hundreds
    lc.setChar(0,1,0,false); //to show 0 as initial number - tens
    lc.setChar(0,2,0,false); //to show 0 as initial number - units
    lc.setChar(0,3,0,false); //to show 0 as initial number - doesn't exist as 3-digit
}

void loop() {

// if FC51 changes the state, it does +1
ChangeStateFC51();
if (FC51 == 1) { 
  Plus1();
  Update7segment(count);
  Serial.print("FC51=");
  Serial.println(FC51);
  FC51=0;
  }

// if PushButtonPlus1 is active, it does +1
PushButtonPlus1();
if (ButtonPlus1 == 1) { 
  Plus1();
  Update7segment(count);
  Serial.print("ButtonPlus1=");
  Serial.println(ButtonPlus1);
  ButtonPlus1=0;
  }

// if PushButtonMinus1 is active, it does -1
PushButtonMinus1();
if (ButtonMinus1 == 1) { 
  Minus1();
  Update7segment(count);
  Serial.print("ButtonMinus1=");
  Serial.println(ButtonMinus1);
  ButtonMinus1=0;
  }

// if PushButtonReset is active, it resets to 0
PushButtonReset();
if (ButtonReset == 1) { 
  Reset();
  Update7segment(count);
  Serial.print("ButtonReset=");
  Serial.println(ButtonReset);
  ButtonReset=0; 
  }

}

void ChangeStateFC51() {

  // read the FC51 input pin:
  buttonStateFC51 = digitalRead(PinFC51);

  // compare the buttonState to its previous state
  if (buttonStateFC51 != lastButtonStateFC51) {
    // if the state has changed from low to high, increment the counter otherwise don't
    if (buttonStateFC51 == HIGH) {
      FC51=1;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonStateFC51 = buttonStateFC51;

}

void PushButtonPlus1() {
  
  // read the pushbutton input pin:
  buttonStatePlus1 = digitalRead(PinButtonPlus1);

  // compare the buttonState to its previous state
  if (buttonStatePlus1 != lastButtonStatePlus1) {
    // if the state has changed from low to high, increment the counter otherwise don't
    if (buttonStatePlus1 == HIGH) {
      ButtonPlus1=1;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonStatePlus1 = buttonStatePlus1;
  
}

void PushButtonMinus1() {
  
  // read the pushbutton input pin:
  buttonStateMinus1 = digitalRead(PinButtonMinus1);

  // compare the buttonState to its previous state
  if (buttonStateMinus1 != lastButtonStateMinus1) {
    // if the state has changed from low to high, increment the counter otherwise don't
    if (buttonStateMinus1 == HIGH) {
      ButtonMinus1=1;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonStateMinus1 = buttonStateMinus1;
  
}

void PushButtonReset() {
  
  // read the pushbutton input pin:
  buttonStateReset = digitalRead(PinButtonReset);

  // compare the buttonState to its previous state
    if (buttonStateReset != lastButtonStateReset) {
    // if the state has changed from low to high, increment the counter otherwise don't
  if (buttonStateReset == HIGH) {
      ButtonReset=1;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
    }
  // save the current state as the last state, for next time through the loop
  lastButtonStateReset = buttonStateReset;
  
}

void Plus1()
{
  if (count>=999) {
    count = 0;
  } else {
    count = count + 1;
  }
}

void Minus1()
{
  if (count<=0) {
    count = 0;
  } else {
    count = count - 1;
  }
}

void Reset()
{
  count = 0;
}

void Update7segment(int v) {  
    
    int ones;  
    int tens;  
    int hundreds; 

    //set the different numbers
    ones=v%10;  
    v=v/10; 
     
    tens=v%10;  
    v=v/10;
    
    hundreds=v;  

    //print the numbers digit by digit
    lc.setDigit(0,0,(byte)hundreds,false);
    lc.setDigit(0,1,(byte)tens,false); 
    lc.setDigit(0,2,(byte)ones,false);

  Serial.print("count : ");
  Serial.println(count);
  Serial.print("v : ");
  Serial.println(v);
  Serial.print("ByteHun : ");
  Serial.println((byte)hundreds);
  Serial.print("ByteTen : ");
  Serial.println((byte)tens);
  Serial.print("ByteOne : ");
  Serial.println((byte)ones);

}

I now need to build the real protoype, and see if 1 IR sensor works with the plastic bags, or if need to put more, or change to the piezoelectric one.

Thanks again for your help,

Nagaro:
I have 1 mini-issue : when i start the arduino, the variable FC51 always goes to 1 by itself, so the counter starts at 1.

Which is button FC51 in the photo? What is the voltage on the PinFC51 when the switch is not actuated?

FC51 is actually the IR sensor (on the left on the picture). It receives the voltage from the computer, so 5V i believe.
It’s not a big issue, but it would be better to have a clean code.

Thx

My guess: the Arduino starts up faster than the sensor, and upon starting up the sensor's output changes which is (correctly!) sensed by the Arduino.

Simple and often effective solution: add a delay() in setup(). Something like 100-1000 ms probably.

Hi,

Good analysis, that’s probably the case. I’ll do so and see what happens :slight_smile:
Thank you

I found the issue : the IR sensor is by default set as High. When an object is in front, it goes to Low.
As i’m stating the « LastButtonStatus » as false by default, but the ir sensor itself is by default as high, the change status function runs directly when the arduino starts, and increments the count.
To solve this, i just needed to change the « LastButtonStatus » from false to true, and here we go :wink:

I built a prototype of the box, and as expected, 1 sensor is good for normal stuff, but not enough to detect the bags falling. I’ll try to put directly 4 sensors as a cross, modify the code and see what’s the outcome.
Otherwise i move to a piezoelectric sensor. The good thing is that the code won’t change that much :slight_smile:

I’ll keep you updated, like always.

Ah, well done.
That doesn't explain, though, why it worked fine after a reset as you mentioned in #48.

Thanks.
Actually it does : what i called « reset » was my reset button i’ve implemented, not the reset button directly on the arduino. Pressing this reset on the arduino was doing the issue too :slight_smile:
Sorry, maybe i should have called my button different :slight_smile:

So now everything is fine, it only needs to work with this plastic bags with jewelry inside.

Hi,

I made a first protoype of the box (in carton paper), having both ir sensors as i wanted first. It is working, but not accurate enough.

So i built a second protoype (see picture attached), using the idea of the ramp.
I figured out that both ir sensors is front of each other is actually working as a beam break (2 beam breaks, as there are 2 sensors). So i only need to hide 1 sensor (the small piece of carton on the left), and it’s working really accurate.
Now the problem is that the ramp makes the piece falling slowlier, which is not good for the productivity of counting. So i’ll not consider the ramp anymore, meaning noto considering using a piezoelectric sensor anymore.

So i’ll come back to the 1st idea, but putting the 2 sensors in front of each other.
I’ll also try to had 2 more sesnors, to have a bigger surface to cover.
Let’s see how it will work :slight_smile:

Little by little we are getting to the final solution.

A ramp does't preclude an impact sensor, as it's the hit of arrival you're measuring, not presence on the ramp.

You’re right, i didn’t consider this :slight_smile:
So piezo might be back again. Probably for the next gen :slight_smile:

I improved again the prototype, now using the duplo from my sons (see picture).
As i need a quite big whole for the bags, 4 IR sensors are not enough. I’ll need to put 6.
But the good thing is that only 3 sensors need to be connected to the arduino (the ones placed on the left). The 3 on the right are only there to create the break beam, and don’t need to be connected (so i don’t need the small carton to hide anymore).
I also put a delay of 150 ms for each sensor, so that the 3 sensors are not processed at the same time. I’ll need to test in real conditions to see if i need to extend this delay or not.

As i’m missing 2 IR sensors, i ordered new ones. So next post in a few days :slight_smile:

See you,

Get a second set that goes perpendicular, the gaps between the sensors are big enough for a small bag to slip through when aligned just right (this sooner or later will happen).

And why the delay? Only gives more opportunity for bags to slip through. I'd read the sensors as often as possible, but after detecting and counting a bag wait some time (300-500 ms maybe) or for the sensors to not detect the bag any more before counting a new one.

The delay i’ve implemented is actually what you just explained : it waits only after detecting and counting it.

I’ve tried it now with the 6 IR sensors, it works pretty well. But i’ve realized that we count the person is throwing the bags slowlier, as he check everytime if it counts correctly or not. So i would like to include a buzzer, to beep for each count (so we don’t need to check the numbers).

I read there are active and passive buzzers, but i would like to have the easiest possible, with the easiest code. Is it then the active or the passive ?

A basic buzzer will just produce a beep when powered on. May be able to connect it directly to an output pin, check current draw.

Hi,

I found the solution for the buzzer. And it works just awesome !

In general, the protoype is working quite good. Not 100% accurate as i would expect, but i can still find a way to optimize it.

Now is coming the time to transform this prototype to a « real » system.
But i’ve never done it.
I can imagine i need to build a PCB where i can put all buttons and electronical parts.

Do you know where i could design it, and who could produce it for ? Would you have any tipp regarding this ?

Thank you for the help :slight_smile:

I'm using KiCAD to design, then SeeedStudio to make my PCBs, and assemble them myself.

For a 1-2 off project this is generally not necessary, soldered on a piece of perfboard works just as well.

Hi wvmarle,

Sorry for the late reply, but it doesn’t mean this project didn’t move forward.
I showed it at work, they loved the concept ! So now i need to create the prototype with KiCAD and SeedStudio. As i lever used any of them, i need to get use to it to manage both in a proper way. And when i see on SeedStudio all the parameters possible to put (no of layers, surface finish, minimum solder mask dam...etc...), it might take a bit time :slight_smile:

In parallel, i bought a vibration sensor SW-420, and tried the concept of launching on a plate which will count the pieces.
It’s not really accurate yet, i have some issues with the code, but i’ll see the result i’ll reach.
And let you know of course :slight_smile:

See you soon i guess

Hi,

I've modified the code to be adapted to the SW-420, but now when i press on one of my button, it almost never does anything.
I have the feeling something is "blocking" the arduino, and only at a specific moment the Arduino is "free" and the action from pressing a button is taken.

Below the code :

#include "LedControl.h"
LedControl lc = LedControl(4,5,6,4);

// ----- Code for Change State for FC-51
// this constant won't change:
const int  PinButtonPlus1 = 8;    // the pin that the pushbutton is attached to
const int  PinButtonMinus1 = 9;    // the pin that the pushbutton is attached to
const int  PinButtonReset = 10;    // the pin that the pushbutton is attached to
const int PinLED = 4;       // the pin that the LED is attached to
const int PinBuzzer = 7;
const int PinVibr = 13;
const long VibrTresh = 3000; //Treshold for the vibration sensor to count or not

// Variables will change:
bool buttonStateVibr = false;         // current state of the VibrationSensor
bool lastButtonStateVibr = false;     // previous state of the VibrationSensor

bool buttonStatePlus1 = false;         // current state of the button
bool lastButtonStatePlus1 = false;     // previous state of the button

bool buttonStateMinus1 = false;         // current state of the button
bool lastButtonStateMinus1 = false;     // previous state of the button

bool buttonStateReset = false;         // current state of the button
bool lastButtonStateReset = false;     // previous state of the button

bool Vibr = false;
bool ButtonPlus1 = false;
bool ButtonMinus1 = false;
bool ButtonReset = false;

// variables used for the count
int ones;  
int tens;  
int hundreds;

// ----- Code for Max7219 + LEDs
int count = 0;


void setup()
{

// ----- Code for Change State for FC-51
  // initialize the button pin as an input:
  pinMode(PinVibr, INPUT);
  pinMode(PinButtonPlus1, INPUT);
  pinMode(PinButtonMinus1, INPUT);
  pinMode(PinButtonReset, INPUT);
  
  // initialize the LED as an output:
  pinMode(PinLED, OUTPUT);
  pinMode (PinBuzzer, OUTPUT);
  
  // initialize serial communication:
  Serial.begin(9600);

// ----- Turn OFF the tone
  digitalWrite(PinBuzzer,HIGH); //LOW is ON, HIGH is OFF


// ----- Code for Max7219 + LEDs
    lc.shutdown(0,false); //to activate the led's
    lc.setIntensity(0,5); //to define the brightness of the led's
    lc.clearDisplay(0); //to cancel all info on the led's
    lc.setDigit(0,0,0,false); //to show 0 as initial number - hundreds
    lc.setChar(0,1,0,false); //to show 0 as initial number - tens
    lc.setChar(0,2,0,false); //to show 0 as initial number - units
    lc.setChar(0,3,0,false); //to show 0 as initial number - doesn't exist as 3-digit

}

void loop() {

// if Vibr changes the state, it does +1
ChangeStateVibr();
if (Vibr == true) { 
  Plus1();
  Update7segment(count);
  Serial.print("Vibr=");
  Serial.println(Vibr);
  Vibr=false;
  BeepPlus10();
  delay(150); // that 2 or more sensors do not overlap
}

// if PushButtonPlus1 is active, it does +1
PushButtonPlus1();
if (ButtonPlus1 == true) { 
  Plus1();
  Update7segment(count);
  Serial.print("ButtonPlus1=");
  Serial.println(ButtonPlus1);
  ButtonPlus1=false;
  BeepPlus10();
 }

// if PushButtonMinus1 is active, it does -1
PushButtonMinus1();
if (ButtonMinus1 == true) { 
  Minus1();
  Update7segment(count);
  Serial.print("ButtonMinus1=");
  Serial.println(ButtonMinus1);
  ButtonMinus1=false;
 }

// if PushButtonReset is active, it resets to 0
PushButtonReset();
if (ButtonReset == true) { 
  Reset();
  Update7segment(count);
  Serial.print("ButtonReset=");
  Serial.println(ButtonReset);
  ButtonReset=false; 
}

} //end of proc

void ChangeStateVibr() {

  // read the Vibr input pin:
  unsigned long measurement;
  measurement = pulseIn (PinVibr, HIGH);  //wait for the pin to get HIGH and returns measurement
  delay(10);
  Serial.print("measurement = ");
  Serial.println(measurement);
  if (measurement >= VibrTresh){
    buttonStateVibr = true;
  }
  else{
    if (measurement == 0){ //the vibr needs to go back to 0 if it wants to count again
      buttonStateVibr = false;
    }
  }
  
  // compare the buttonState to its previous state
  if (buttonStateVibr != lastButtonStateVibr) {
    // if the state has changed from less than VibrTres to more than VibrTres, increment the counter otherwise don't
    if (buttonStateVibr == true) {
      Vibr=true;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonStateVibr = buttonStateVibr;

}

void PushButtonPlus1() {
  
  // read the pushbutton input pin:
  buttonStatePlus1 = digitalRead(PinButtonPlus1);

  // compare the buttonState to its previous state
  if (buttonStatePlus1 != lastButtonStatePlus1) {
    // if the state has changed from low to high, increment the counter otherwise don't
    if (buttonStatePlus1 == HIGH) {
      ButtonPlus1=true;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonStatePlus1 = buttonStatePlus1;
  
}

void PushButtonMinus1() {
  
  // read the pushbutton input pin:
  buttonStateMinus1 = digitalRead(PinButtonMinus1);

  // compare the buttonState to its previous state
  if (buttonStateMinus1 != lastButtonStateMinus1) {
    // if the state has changed from low to high, increment the counter otherwise don't
    if (buttonStateMinus1 == HIGH) {
      ButtonMinus1=true;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  lastButtonStateMinus1 = buttonStateMinus1;
  
}

void PushButtonReset() {
  
  // read the pushbutton input pin:
  buttonStateReset = digitalRead(PinButtonReset);

  // compare the buttonState to its previous state
    if (buttonStateReset != lastButtonStateReset) {
    // if the state has changed from low to high, increment the counter otherwise don't
  if (buttonStateReset == HIGH) {
      ButtonReset=true;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
    }
  // save the current state as the last state, for next time through the loop
  lastButtonStateReset = buttonStateReset;
  
}

void Plus1()
{
  if (count>=999) {
    count = 0;
  } else {
    count = count + 1;
  }
}

void Minus1()
{
  if (count<=0) {
    count = 0;
  } else {
    count = count - 1;
  }
}

void Reset()
{
  count = 0;
}

void Update7segment(int v) {  

    //set the different numbers
    ones=v%10;  
    v=v/10; 
     
    tens=v%10;  
    v=v/10;
    
    hundreds=v;  

    //print the numbers digit by digit
    lc.setDigit(0,0,(byte)hundreds,false);
    lc.setDigit(0,1,(byte)tens,false); 
    lc.setDigit(0,2,(byte)ones,false);

} 

void BeepPlus10()
{
    //Tone
    if (ones == 0) {
    digitalWrite(PinBuzzer,LOW);
    tone(PinBuzzer, 1000, 100); //pin,hertz,duration
    delay(100); //delay start at the same time than tone; so thedelay should be at least the same than the duration
    digitalWrite(PinBuzzer,HIGH);
    }
}

Maybe you'll find something weird and not written properly ?

Thank you for your help,

Nagaro:
I have the feeling something is "blocking" the arduino

I spotted at least two delay() calls in that code on a quick glance, those are blocking. How badly they block depend on the complete code flow, didn't analyse that.

So definitely room for improvement. Write all your functions non-blocking and return as soon as possible, make sure your loop() calls them all one after the other, so in turn you can rely on your functions being called frequently and replace those delay() calls by millis() based timing.