1

I am new to Arduino and I am working on a project. This project inspired me and I tried doing it.

The following code was provided in the description:

int maxPeople = 5; // maximum number of people allowed before the alarm goes off
int sensitivity = 5; //lower values will make it more sensitive and higher values will make it less 
sensitive
//---------------------------------------------------


#include <TM1637.h>

int currentPeople = 0;

int buzzer = 8;

TM1637 tm(2,3);

int sensor1[] = {4,5};
int sensor2[] = {6,7};
int sensor1Initial;
int sensor2Initial;

String sequence = "";

int timeoutCounter = 0;

void setup() {
  //Setup code
  Serial.begin(9600);
  pinMode(buzzer, OUTPUT);
  tm.init();
  tm.set(2);

  delay(500);
  sensor1Initial = measureDistance(sensor1);
  sensor2Initial = measureDistance(sensor2);
}

void loop() {
  //Read ultrasonic sensors
  int sensor1Val = measureDistance(sensor1);
  int sensor2Val = measureDistance(sensor2);

  //Process the data
  if(sensor1Val < sensor1Initial - 30 && sequence.charAt(0) != '1'){
    sequence += "1";
  }else if(sensor2Val < sensor2Initial - 30 && sequence.charAt(0) != '2'){
    sequence += "2";
  }

  if(sequence.equals("12")){
    currentPeople++;  
    sequence="";
    delay(550);
  }else if(sequence.equals("21") && currentPeople > 0){
    currentPeople--;  
    sequence="";
    delay(550);
  }

  //Resets the sequence if it is invalid or timeouts
  if(sequence.length() > 2 || sequence.equals("11") || sequence.equals("22") || timeoutCounter > 200) 
 {
    sequence="";  
  }

  if(sequence.length() == 1){ //
    timeoutCounter++;
  }else{
    timeoutCounter=0;
  }

  //Print values to serial
  Serial.print("Seq: ");
  Serial.print(sequence);
  Serial.print(" S1: ");
  Serial.print(sensor1Val);
  Serial.print(" S2: ");
  Serial.println(sensor2Val);

  //Display current people count on 4-digit display
  tm.display(3, currentPeople % 10);
  int pos2 = currentPeople / 10;
  tm.display(2, pos2 % 10);
  int pos1 = pos2 / 10;
  tm.display(1, pos1 % 10);
  int pos0 = pos1 / 10;
  tm.display(0, pos0 % 10);

  //If the number of people is too high, trigger the buzzer
  if(currentPeople > maxPeople){
    tone(buzzer, 1700);  
  }else{
    noTone(buzzer);  
  }
}

//Returns the distance of the ultrasonic sensor that is passed in
//a[0] = echo, a[1] = trig
int measureDistance(int a[]) {
  pinMode(a[1], OUTPUT);
  digitalWrite(a[1], LOW);
  delayMicroseconds(2);
  digitalWrite(a[1], HIGH);
  delayMicroseconds(10);
  digitalWrite(a[1], LOW);
  pinMode(a[0], INPUT);
  long duration = pulseIn(a[0], HIGH, 100000);
  return duration / 29 / 2;
}

The required libraries are installed. I uploaded this on my Arduino nano and it worked fine. I varied the maxPeople and checked, then too it worked correctly. The third I made objects enter and leave the room by crossing the ultrasonic sensors. It seemed to work correctly, the maximum count (maxPeople) got reached and the buzzer went on. Then I made the object leave the room. Instead of decreasing the number in the display (TM1637 4 digit display) kept on increasing.

Then I turned the USB source OFF and tried again. Again it worked correctly once or twice and the same problem persists.

Sometimes even before the max count is reached, while making an object leave, the count gets increased. And sometimes the count in the display stays still at 0000 or oscillate between '''0000''' and '''0001'''.

(I thought it may be a fault in the Arduino or the ultrasonic sensor or the display, but I checked them with other open-source programs, they worked fine.)

I also tried allocating different pins to the buzzer, sensors and display, still the problem persists.

The declared integer sensitivity is never used in the code. Someone has commented. I tried that too, even then it doesn't work properly.

Is there any mistake in the code that causes this problem or something else? I am stuck on this since last week.

Any help is appreciated.


Edit:
As per @Michel's comment, I tried to change the strings into character arrays.

int maxPeople = 5; // maximum number of people allowed before the alarm goes off
int sensitivity = 5; //lower values will make it more sensitive and higher values will make it less sensitive
//---------------------------------------------------


#include <TM1637.h>

int currentPeople = 0;

int buzzer = 8;

TM1637 tm(2, 3);

int sensor1[] = {4, 5};
int sensor2[] = {6, 7};
int sensor1Initial;
int sensor2Initial;

char sequence[2];

int timeoutCounter = 0;

void setup() {
  //Setup code
  Serial.begin(9600);
  pinMode(buzzer, OUTPUT);
  tm.init();
  tm.set(2);

  delay(500);
  sensor1Initial = measureDistance(sensor1);
  sensor2Initial = measureDistance(sensor2);
}

void loop() {
  //Read ultrasonic sensors
  int sensor1Val = measureDistance(sensor1);
  int sensor2Val = measureDistance(sensor2);

  //Process the data
  if (sensor1Val < sensor1Initial - 30 && sequence[0] != '1') {
    strcat(sequence, "1");
  } else if (sensor2Val < sensor2Initial - 30 && sequence[0] != '2') {
    strcat(sequence, "2");
  }

  if (strcmp(sequence, "12") == 0) {
    currentPeople++;
    sequence[0] = '\0';
    sequence[1] = '\0';
    delay(550);
  } else if (strcmp(sequence, "21") == 0 && currentPeople > 0) {
    currentPeople--;
    sequence[0] = '\0';
    sequence[1] = '\0';
    delay(550);
  }

  //Resets the sequence if it is invalid or timeouts
  if (strlen(sequence) > 2 || strcmp(sequence, "11") == 0 || strcmp(sequence, "22") == 0 || timeoutCounter > 200) {
    sequence[0] = '\0';
    sequence[1] = '\0';

  }

  if (strlen(sequence) == 1) { //
    timeoutCounter++;
  } else {
    timeoutCounter = 0;
  }

  //Print values to serial
  Serial.print("Seq: ");
  Serial.print(sequence);
  Serial.print(" S1: ");
  Serial.print(sensor1Val);
  Serial.print(" S2: ");
  Serial.println(sensor2Val);

  //Display current people count on 4-digit display
  tm.display(3, currentPeople % 10);
  int pos2 = currentPeople / 10;
  tm.display(2, pos2 % 10);
  int pos1 = pos2 / 10;
  tm.display(1, pos1 % 10);
  int pos0 = pos1 / 10;
  tm.display(0, pos0 % 10);

  //If the number of people is too high, trigger the buzzer
  if (currentPeople > maxPeople) {
    tone(buzzer, 1700);
  } else {
    noTone(buzzer);
  }
}

//Returns the distance of the ultrasonic sensor that is passed in
//a[0] = echo, a[1] = trig
int measureDistance(int a[]) {
  pinMode(a[1], OUTPUT);
  digitalWrite(a[1], LOW);
  delayMicroseconds(2);
  digitalWrite(a[1], HIGH);
  delayMicroseconds(10);
  digitalWrite(a[1], LOW);
  pinMode(a[0], INPUT);
  long duration = pulseIn(a[0], HIGH, 100000);
  return duration / 29 / 2;
}

Is there any mistake in this? On uploading this code, the display stops at '0001' and doesn't work further.

8
  • 2
    It might be worthwhile to get rid of the String type and use a fixed character array. Because of dynamic memory allocation to String you might get memory gaps, and eventually running out of memory. – Michel Keijzers May 5 at 11:25
  • 1
    You will need to change quite some things, like defining a constant for the MAX array size, and use functions strcat, strln and strcmp instead of adding, checking the size and comparing. – Michel Keijzers May 5 at 11:55
  • 1
    When using C strings, you have also to keep one \0 for the end symbol, so to store "01", you need 3 bytes., otherwise the strlen/strcmp will not work. – Michel Keijzers May 5 at 13:58
  • 1
    Also I think that with - 30 you want to convert '0' to 0, but then you need to use 0x30 (hex), which is '0', or better: use '0' directlly (with a cast if needed) – Michel Keijzers May 5 at 14:00
  • 1
    You can use the statement, I'm not sure if it will do what you want but it's a valid statement syntactically wise. Also, you can probably skip all sequence[1] = '\0'; statements. When the first element is 0, a string is considered to end there and e.g. strcmp does not check further. – Michel Keijzers May 7 at 10:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.