Проблема с подсчетом количества посетителей в моей умной комнате - PullRequest
0 голосов
/ 17 апреля 2020

Mealy Diagram Я строю счетчик посетителей в своей комнате, используя Arduino, ИК-передатчик и два ИК-датчика SHARP. Датчики подсчитывают количество людей в моей комнате - один человек включает свет, больше ничего не делает, а ноль выключает свет. ИК-передатчик работает отлично (он включает / выключает свет), так что при обнаружении, но у меня есть проблема и вопрос.

У меня вопрос, есть ли возможность сделать функцию и вызвать ее дважды вместо того, чтобы повторяться внутри l oop? если да, то как? в основном они симметричны c, но все же имеют некоторые различия, такие как флаги и манипуляции с num_people.

Моя главная проблема сейчас заключается в подсчете num_people, и я обнаружил, что эта строка является проблемой: num_people = (num_people > 0) ? num_people-1 : 0; Когда я Поместив эту строку в комментарий, я могу сосчитать больше, чем одного человека, но когда меня нет, он перебирает код и считает 1,0,1,0,1,0 (только при входе в комнату). Нужно сказать, что когда я go выходит, он уменьшает num_people, как и должно, и когда на нуле сохраняет это число.

Код здесь:



/*
    Smart Light V1.0 Software
    ==========================
    Copyright (C) 2020 Yuval Kedar - KD Tech
    The program counts visitors in my room and controls the light using SHARP IR sensors
    Board: Arduino Pro Mini
*/


#include "Arduino.h"
#include <IRremote.h>
// TODO: try a dedicated library for the sensors. Raw readings aren't the best way to do that - need to overcome oversampling, debouncing, hysteresis, etc.

#define IR_TRANSMITTER_PIN  (3)
#define SENS_1_PIN (A1)
#define SENS_2_PIN (A0)

#define SENS_1_MIN  (160)
#define SENS_2_MIN  (160)
#define MAX_TIME    (1000)
#define IR_KEY      (0x68B92)
#define DEBOUNCE_MS (300)

IRsend irsend;

uint8_t num_people = 0;
uint8_t prev_num_people = 0;
bool sens_1_flag = 0;
bool sens_2_flag = 0;
uint32_t timeout;

void setup() {
    Serial.begin(115200);
    pinMode(SENS_1_PIN, INPUT);
    pinMode(SENS_2_PIN, INPUT);
    pinMode(IR_TRANSMITTER_PIN, OUTPUT);
    Serial.println(F(
                "_______________________________\n"
                "\n"
                "      S M A R T    R O O M     \n"
                "_______________________________\n"
                "\n"
                "      Made by KD Technology    \n"
                "\n"));
}

void loop() {
    uint16_t sens_1_val = analogRead(SENS_1_PIN);
    uint16_t sens_2_val = analogRead(SENS_2_PIN);
    /*
    Serial.print("LDR 1: ");
    Serial.print(sens_1_val);
    Serial.print("\t LDR 2: ");
    Serial.println(sens_2_val);
    delay(200);
    */

    //TODO: there is a duplication here. Create a function and call it twice inside the loop.

    //Someone goes in
    if (sens_1_val < SENS_1_MIN && sens_2_val > SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 0) sens_2_flag = 1;
    if (sens_1_val > SENS_1_MIN && sens_2_val < SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 1) {
        // TODO: add timeout to while loop. Otherwise, the program will stuck because of a sensor reading.
        // timeout = millis() + MAX_TIME;
        // while (sens_2_val > SENS_2_MIN && (millis() > timeout));
        num_people = num_people+1;
        if (num_people == 1 && prev_num_people == 0) {
            irsend.sendSony(IR_KEY, 20);
            Serial.println("BLING!");
        }
        sens_1_flag = 0;
        sens_2_flag = 0;
        prev_num_people = num_people;           
        Serial.print("People in the room: ");
        Serial.println(num_people);
        delay(DEBOUNCE_MS);
    }

    //Someone goes out
    if (sens_1_val > SENS_1_MIN && sens_2_val < SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 0) sens_1_flag = 1;
    if (sens_1_val < SENS_1_MIN && sens_2_val > SENS_2_MIN && sens_1_flag == 1 && sens_2_flag == 0) {
        timeout = millis() + MAX_TIME;
        while (sens_1_val > SENS_1_MIN && (millis() > timeout));
        num_people = (num_people > 0) ? num_people-1 : 0;
        if (num_people == 0 && prev_num_people != 0) {
            irsend.sendSony(IR_KEY, 20);
            Serial.println("BLING!");
        }
        sens_1_flag = 0;
        sens_2_flag = 0;
        prev_num_people = num_people;           
        Serial.print("People in the room: ");
        Serial.println(num_people);
        delay(DEBOUNCE_MS);
    }
}

РЕДАКТИРОВАТЬ:


/*
    Smart Light V1.0 Software
    ==========================
    Copyright (C) 2020 Yuval Kedar - KD Tech
    The program counts visitors in my room and controls the light using SHARP IR sensors
    Board: Arduino Pro Mini
*/


#include "Arduino.h"
#include <IRremote.h>
// TODO: try a dedicated library for the sensors. Raw readings aren't the best way to do that - need to overcome oversampling, debouncing, hysteresis, etc.

#define IR_TRANSMITTER_PIN  (3)
#define SENS_1_PIN (A1)
#define SENS_2_PIN (A0)

#define SENS_1_MIN  (160)
#define SENS_2_MIN  (160)
#define MAX_TIME    (1000)
#define IR_KEY      (0x68B92)
#define DEBOUNCE_MS (300)

IRsend irsend;

uint8_t num_people = 0;
uint8_t prev_num_people = 0;
bool sens_1_flag = 0;
bool sens_2_flag = 0;
uint32_t timeout;

void setup() {
    Serial.begin(115200);
    pinMode(SENS_1_PIN, INPUT);
    pinMode(SENS_2_PIN, INPUT);
    pinMode(IR_TRANSMITTER_PIN, OUTPUT);
    Serial.println(F(
                "_______________________________\n"
                "\n"
                "      S M A R T    R O O M     \n"
                "_______________________________\n"
                "\n"
                "      Made by KD Technology    \n"
                "\n"));
}

void loop() {
    uint16_t sens_1_val = analogRead(SENS_1_PIN);
    uint16_t sens_2_val = analogRead(SENS_2_PIN);
    /*
    Serial.print("LDR 1: ");
    Serial.print(sens_1_val);
    Serial.print("\t LDR 2: ");
    Serial.println(sens_2_val);
    delay(200);
    */

    //TODO: there is a duplication here. Create a function and call it twice inside the loop.

    //Someone goes in
    if (sens_1_val < SENS_1_MIN && sens_2_val > SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 0) sens_2_flag = 1;
    if (sens_1_val > SENS_1_MIN && sens_2_val < SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 1) {
        // TODO: add timeout to while loop. Otherwise, the program will stuck because of a sensor reading.
        // timeout = millis() + MAX_TIME;
        // while (sens_2_val > SENS_2_MIN && (millis() > timeout));
        num_people += 1;
        if (num_people == 1 && prev_num_people == 0) {
            irsend.sendSony(IR_KEY, 20);
            Serial.println("BLING!");
        }
        sens_1_flag = 0;
        sens_2_flag = 0;
        prev_num_people = num_people;           
        Serial.print("People in the room: ");
        Serial.println(num_people);
        delay(DEBOUNCE_MS);
    }

    //Someone goes out
    if (sens_1_val > SENS_1_MIN && sens_2_val < SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 0) sens_1_flag = 1;
    if (sens_1_val < SENS_1_MIN && sens_2_val > SENS_2_MIN && sens_1_flag == 1 && sens_2_flag == 0) {
        // timeout = millis() + MAX_TIME;
        // while (sens_1_val > SENS_1_MIN && (millis() > timeout));
        // num_people = (num_people > 0) ? num_people-1 : 0;
        if (num_people > 1) num_people -= 1;
        if (num_people == 1 && prev_num_people != 0) {
            num_people -= 1;
            irsend.sendSony(IR_KEY, 20);
            Serial.println("BLING!");
        }
        sens_1_flag = 0;
        sens_2_flag = 0;
        prev_num_people = num_people;           
        Serial.print("People in the room: ");
        Serial.println(num_people);
        delay(DEBOUNCE_MS);
    }
}

РАЗЛИЧНЫЙ ПОДХОД:

Я выяснил новое состояние машины. Мне нужно пройти 4 состояния: 1. датчик_1 обнаруживает, а датчик_2 не распознает 2. оба датчика обнаруживают 3. датчик_2 обнаруживает, а датчик_1 не 4. ни одно из них не обнаруживает.

Вот мой код:


/*
    Smart Light V1.0 Software
    ==========================
    Copyright (C) 2020 Yuval Kedar - KD Tech
    The program counts visitors in my room and controls the light using SHARP IR sensors
    Board: Arduino Pro Mini
*/


#include "Arduino.h"
#include <IRremote.h>
// TODO: try a dedicated library for the sensors. Raw readings aren't the best way to do that - need to overcome oversampling, debouncing, hysteresis, etc.

#define IR_TRANSMITTER_PIN  (3)
#define SENS_1_PIN (A0)
#define SENS_2_PIN (A1)

#define SENS_1_MIN  (115)
#define SENS_2_MIN  (115)
#define IR_KEY      (0x68B92)
#define DEBOUNCE_MS (2000)


IRsend irsend;

int8_t num_people = 0;
uint8_t state = 0;

void setup() {
    Serial.begin(115200);
    pinMode(SENS_1_PIN, INPUT);
    pinMode(SENS_2_PIN, INPUT);
    pinMode(IR_TRANSMITTER_PIN, OUTPUT);
    Serial.println(F(
                "_______________________________\n"
                "\n"
                "      S M A R T    R O O M     \n"
                "_______________________________\n"
                "\n"
                "      Made by KD Technology    \n"
                "\n"));
}

void loop() {
    uint16_t sens_1_val = analogRead(SENS_1_PIN);
    uint16_t sens_2_val = analogRead(SENS_2_PIN);
    switch (state) {
        case 0:
            if ((sens_1_val > SENS_1_MIN) && (sens_2_val < SENS_2_MIN)) {
            // if (!sens_1_val && sens_2_val) {
                state = 4;
                Serial.println("0 to 4");
            }
            if ((sens_2_val > SENS_2_MIN) && (sens_1_val < SENS_1_MIN)) {
            // if (!sens_2_val && sens_1_val) {
                state = 1;
                Serial.println("0 to 1");
            }
            break;
        case 1:
            if ((sens_1_val > SENS_1_MIN) && (sens_2_val > SENS_2_MIN)) {
            // if (!sens_1_val && !sens_2_val) {
                state = 2;
                Serial.println("1 to 2");
            } else state = 0;
            break;
        case 2:
            if ((sens_1_val > SENS_1_MIN) && (sens_2_val < SENS_2_MIN)) {
            // if (!sens_1_val && sens_2_val) {
                state = 3;
                Serial.println("2 to 3");
            } else state = 1;
            break;
        case 3:
            if ((sens_1_val < SENS_1_MIN) && (sens_2_val < SENS_2_MIN)) {   //someone went out
            // if (sens_1_val && sens_2_val) {  //someone went out
                num_people -= 1;
                if (num_people == 0) {
                    irsend.sendSony(IR_KEY, 20);
                    Serial.println("BLING!");
                }
                else if (num_people == -1) num_people = 0;
                Serial.print("People in the room: ");
                Serial.println(num_people);
                // delay(DEBOUNCE_MS);
                state = 0;
            }  else state = 2;
            break;
        case 4:
            if ((sens_1_val > SENS_1_MIN) && (sens_2_val > SENS_2_MIN)) {
            // if (!sens_1_val && !sens_2_val) {
                state = 5;
                Serial.println("4 to 5");
            } else state = 0;
            break;
        case 5:
            if ((sens_2_val > SENS_2_MIN) && (sens_1_val < SENS_1_MIN)) {
            // if (!sens_2_val && sens_1_val) {
                state = 6;
                Serial.println("5 to 6");
            } else state = 4;
            break;
        case 6:
            if ((sens_1_val < SENS_1_MIN) && (sens_2_val < SENS_2_MIN)) {   //someone came in
            // if (sens_1_val && sens_2_val) {  //someone came in
                num_people += 1;
                if (num_people == 1) {
                    irsend.sendSony(IR_KEY, 20);
                    Serial.println("BLING!");
                }
                Serial.print("People in the room: ");
                Serial.println(num_people);
                // delay(DEBOUNCE_MS);
                state = 0;
            } else state = 5;
            break;
    }
    // Serial.print("LDR 1: ");
    // Serial.print(sens_1_val);
    // Serial.print("\t LDR 2: ");
    // Serial.println(sens_2_val);
    // delay(DEBOUNCE_MS);
}

Сначала я проверил код с помощью кнопок и цифровых показаний, и он работал отлично! Но затем, когда я вернулся к аналоговым показаниям, возникла проблема: я напечатал на последовательном мониторе строку в каждом состоянии, чтобы найти проблему, и заметил, что она переходит все состояния, но когда она достигает последнего состояния и предполагает увеличение \ уменьшить num_people и распечатать его, а это не так. Вместо этого он возвращается в состояние 0 ...

Ответы [ 3 ]

2 голосов
/ 17 апреля 2020

есть ли возможность создать функцию и вызвать ее дважды вместо повторения внутри l oop? если да, то как? они в основном симметричны c, но все же имеют некоторые различия, такие как флаги и манипуляции с num_people.

Наверняка ваши две части очень похожи, и это более заметно при изменении порядка выражений в 2 ifs.

Например, во второй части у вас есть

if (sens_1_val > SENS_1_MIN && sens_2_val < SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 0) sens_1_flag = 1;
if (sens_1_val < SENS_1_MIN && sens_2_val > SENS_2_MIN && sens_1_flag == 1 && sens_2_flag == 0) {

, что эквивалентно тому, что после переупорядочения:

if (sens_2_val < SENS_2_MIN && sens_1_val > SENS_1_MIN && sens_2_flag == 0 && sens_1_flag == 0) sens_1_flag = 1;
if (sens_2_val > SENS_2_MIN && sens_1_val < SENS_1_MIN && sens_2_flag == 0 && sens_1_flag == 1) {

так точно два теста в первой части при замене sens_1_val на sens_2_val и SENS_1_MIN на SENS_2_MIN , и это то же самое в остальные строки.

Затем:

void f(int sens1, int sens1_min, int sens2,int sens2_min, int offset, int bling)
{
    if (sens1 < sens1_min && sens2 > sens2_min && sens_1_flag == 0 && sens_2_flag == 0) sens_2_flag = 1;
    if (sens1 > sens1_min && sens2 < sens2_min && sens_1_flag == 0 && sens_2_flag == 1) {
        timeout = millis() + MAX_TIME;
        while (sens2 > sens2_min && (millis() > timeout));
        if ((num_people += offset) < 0)
          num_people = 0;
        Serial.print("People in the room: ");
        Serial.println(num_people);
        sens_1_flag = 0;
        sens_2_flag = 0;
        delay(DEBOUNCE_MS);
        if (num_people == bling) {
            irsend.sendSony(IR_KEY, 20);
            Serial.println("BLING!");
        }
    }
}

первая часть в вашем коде выполняется с помощью

 f(sens_1_val, SENS_1_MIN, sens_2_val, SENS_2_MIN, 1, 1);
 sens_1_val = sens_2_val = 0;

, а вторая с помощью

f(sens_2_val, SENS_2_MIN, sens_1_val, SENS_1_MIN, -1, 0); 
sens_1_val = sens_2_val = 0;

Я не хотел сбрасывать sens_x_val в функции, чтобы не указывать указатель

В остальном извините, но я не понимаю вашу проблему, объясните больше


редактировать после добавления конечного автомата

Ваш конечный автомат странный, я думаю, вам не нужно так много состояний. Определение машины зависит от того, может ли свет выключаться или включаться вручную кем-то внутри и / или за пределами помещения.

Если свет управляется только вашими датчиками, то больше тайм-аут на случай, если никто не погаснет, или через некоторое время:

enter image description here

Я использую здесь нотацию UML, при переходе '[]' указывает охрану / условие, чтобы соблюдать переход не может быть выполнен, тело после '/' выполняется после того, как переход сделан.

Для управления случаем, когда несколько человек выходят одновременно, но датчики считают только один, я использую тайм-аут.

Если кто-то также может управлять светом внутри комнаты, и свет включается, когда кто-то входит, и свет выключается, когда комната становится пустой / после время ожидания:

enter image description here


редактировать, обнаружена первоначальная проблема

В вашей первоначальной версии ваша проблема была в:

   num_people = (num_people > 0) ? num_people-1 : 0;
   ...
   if (num_people == 0) {
       irsend.sendSony(IR_KEY, 20);
       Serial.println("BLING!");
   }

b потому что при выполнении теста в , если , вы не знаете, включен или выключен ваш свет, вы потеряли эту информацию в первой строке, и вы можете ошибочно принять решение об изменении ее состояния.

редактировать после редактирования кода

Для меня ваш новый код выглядит нормально, в любом случае вы можете обойтись без prev_num_people .

Вы установили prev_num_people to num_people после каждого входа / выхода, поэтому в случае "входите":

   num_people = num_people+1;
   if (num_people == 1 && prev_num_people == 0) {
     irsend.sendSony(IR_KEY, 20);
     Serial.println("BLING!");
   }

до увеличения num_people у вас было prev_num_people == num_people затем после num_people == 1 подразумевается prev_num_people == 0 , и проверять его бесполезно. Просто сделай

if (++num_people == 1) {
   /* light is off, put it on */
   irsend.sendSony(IR_KEY, 20);
   Serial.println("BLING!");
 }

В случае "вышел", а не

   num_people = (num_people > 0) ? num_people-1 : 0;
   if (num_people == 0 && prev_num_people != 0) {
       irsend.sendSony(IR_KEY, 20);
       Serial.println("BLING!");
   }

Просто сделай

 if (--num_people == 0) {
    /* light is on, put it off */
    irsend.sendSony(IR_KEY, 20);
    Serial.println("BLING!");
 }
 else if (num_people == -1) {
    /* light is already off but in past several person
       went out at the same time and only one was count */
    num_people = 0;
 }

Все который предполагает, что вы правильно обнаружили, что кто-то входит / выходит, я не могу вам в этом помочь, я не знаю, как работают ваши датчики.

Обратите внимание, если вы хотите разрешить ручную смену света, который вам нужен запомните состояние света, NumPerson больше не достаточно, чтобы решить, каково текущее состояние света.


отредактируйте вашу новую версию, содержащую:

   if (num_people > 1) num_people -= 1;
   if (num_people == 1 && prev_num_people != 0) {
       num_people -= 1;
       irsend.sendSony(IR_KEY, 20);
       Serial.println("BLING!");
   }

это 'тревожно', потому что когда вы достигаете второго , если , вы знаете только, откуда вы пришли благодаря prev_num_people ( num_people потерял историю), и вы проводите много тестов впустую

Я настоятельно рекомендую вам использовать упрощенную версию, которую я дал вам раньше, без prev_num_people . Чем более простой код, тем легче его читать и тем более он устойчив

1142 *

изменить, чтобы добавить симуляцию

Если я симулирую ваши датчики, ваш код отключается "#if 0":

#include <stdio.h>

int main()
{
  int num_people = 0;
  int real_people = 0;
  int n;

  while (scanf("%d", &n) == 1) {
    real_people += n;

    //Someone goes in
#if 0
    if (sens_1_val < SENS_1_MIN && sens_2_val > SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 0) sens_2_flag = 1;
    if (sens_1_val > SENS_1_MIN && sens_2_val < SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 1)
#else
    if (n > 0)
#endif
    {
      if (++num_people == 1) {
        /* light is off, put it on */
#if 0
        irsend.sendSony(IR_KEY, 20);
        Serial.println("BLING!");
#else
        puts("put light on");
#endif
      }
#if 0
      sens_1_flag = 0;
      sens_2_flag = 0;
      Serial.print("People in the room: ");
      Serial.println(num_people);
      delay(DEBOUNCE_MS);
#else
      printf("People supposed the room: %d (real %d)\n", num_people, real_people);
#endif
    }

    //Someone goes out
#if 0
    if (sens_1_val > SENS_1_MIN && sens_2_val < SENS_2_MIN && sens_1_flag == 0 && sens_2_flag == 0) sens_1_flag = 1;
    if (sens_1_val < SENS_1_MIN && sens_2_val > SENS_2_MIN && sens_1_flag == 1 && sens_2_flag == 0)
#else
    if (n < 0)
#endif
    {
      if (--num_people == 0) {
        /* light is on, put it off */
#if 0
        irsend.sendSony(IR_KEY, 20);
        Serial.println("BLING!");
#else
        puts("put light off");
#endif
      }
      else if (num_people == -1) {
        /* light is already off but in past several person
           went out at the same time and only one was count */
        num_people = 0;
      }
#if 0
      sens_1_flag = 0;
      sens_2_flag = 0;
      prev_num_people = num_people;           
      Serial.print("People in the room: ");
      Serial.println(num_people);
      delay(DEBOUNCE_MS);
#else
      printf("People supposed the room: %d (real %d)\n", num_people, real_people);
#endif
    }
  }
  return 0;
}

для ввода положительного числа соответствуют случаю «приходи», отрицательное число - «хочу выйти». Я также добавил real_people , соответствующее реальному количеству людей в комнате

Компиляция и выполнение:

pi@raspberrypi:/tmp $ gcc -Wall light.c 
pi@raspberrypi:/tmp $ ./a.out
1
put light on
People supposed the room: 1 (real 1)
-1
put light off
People supposed the room: 0 (real 0)
1
put light on
People supposed the room: 1 (real 1)
1
People supposed the room: 2 (real 2)
-1
People supposed the room: 1 (real 1)
1
People supposed the room: 2 (real 2)
-1
People supposed the room: 1 (real 1)
-1
put light off
People supposed the room: 0 (real 0)
2
put light on
People supposed the room: 1 (real 2)
-1
put light off
People supposed the room: 0 (real 1)
-1
People supposed the room: 0 (real 0)
1
put light on
People supposed the room: 1 (real 1)
1
People supposed the room: 2 (real 2)
-2
People supposed the room: 1 (real 0)
^C
pi@raspberrypi:/tmp $ 

Без тайм-аута на вход / выход свет не может погаснуть с конца, кроме случаев, когда 2 человека приходят одновременно, затем 1 уходит, затем снова 1 уходит

В любом случае, вы видите, что алгоритм в порядке, так что если у вас есть проблема в управлении сенсором (код отключен #if 0 #)

1 голос
/ 17 апреля 2020

Предостережение: Это не столько ответ на одну строчку, что у вас есть в вашем вопросе, но и упрощение / очистка вашего кода [в соответствии с вашими комментариями].

Мне было трудно понять вашу логику c [со всей репликацией], поэтому я упростил ее в качестве первого шага. Пока я делал это, другие отвечали, так что вы можете включить их ответы, если будете sh.

Вместо того, чтобы фиксировать все, что я создал, struct, который полностью описывает каждое устройство и некоторые функции, которые действуют на значения в этой структуре.

В любом случае, вот код. Я очень старался, чтобы не сломал вашу существующую логику c, но вы можете проверить это. Надеемся, что упрощение позволит вам увидеть реальную проблему проще:

/*
    Smart Light V1.0 Software
    ==========================
    Copyright (C) 2020 Yuval Kedar - KD Tech
    The program counts visitors in my room and controls the light using
    SHARP IR sensors
    Board: Arduino Pro Mini
*/

#include "Arduino.h"
#include <IRremote.h>
// TODO: try a dedicated library for the sensors. Raw readings aren't the best
// way to do that - need to overcome oversampling, debouncing, hysteresis, etc.

#define IR_TRANSMITTER_PIN  (3)
#define SENS_1_PIN (A1)
#define SENS_2_PIN (A0)

#define SENS_1_MIN  (160)
#define SENS_2_MIN  (160)
#define MAX_TIME    (1000)
#define IR_KEY      (0x68B92)
#define DEBOUNCE_MS (300)

IRsend irsend;

typedef struct {
    int sens_id;
    int sens_pin;
    int sens_min;
    int sens_flag;
    uint16_t sens_val;
} sens_t;

sens_t sensall[2];
#define s1  (&sensall[0])
#define s2  (&sensall[1])

uint8_t num_people = 0;
uint32_t timeout;

void
sensinit(sens_t *sens,int id,int pin,int min)
{

    sens->sens_id = id;
    sens->sens_pin = pin;
    sens->sens_min = min;
    sens->sens_flag = 0;
    pinMode(sens->sens_pin,INPUT);
}

void
sensread(sens_t *sens)
{
    sens->sens_val = analogRead(sens->sens_pin);
}

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

    sensinit(s1,1,SENS_1_PIN,SENS_1_MIN);
    sensinit(s2,2,SENS_2_PIN,s2->sens_min);

    pinMode(IR_TRANSMITTER_PIN, OUTPUT);
    Serial.println(F("_______________________________\n"
        "\n"
        "      S M A R T    R O O M     \n"
        "_______________________________\n"
        "\n"
        "      Made by KD Technology    \n"
        "\n"));
}

int
sensif(int lt_gt,int v1,int v2)
{
    int cond1;
    int cond2;
    int match;

    if (lt_gt) {
        cond1 = (s1->sens_val < s1->sens_min);
        cond2 = (s2->sens_val > s2->sens_min);
    }
    else {
        cond1 = (s1->sens_val > s1->sens_min);
        cond2 = (s2->sens_val < s2->sens_min);
    }

    match = (cond1 && cond2 && (s1->sens_flag == v1) && (s2->sens_flag == v2));

    return match;
}

void
senswait(sens_t *sens,int newval)
{
    timeout = millis() + MAX_TIME;

    // TODO: add timeout to while loop. Otherwise, the program will stuck
    // because of a sensor reading.
    while ((sens->sens_val > sens->sens_min) && (millis() > timeout));

#if 0
    switch (sens->sens_id) {
    case 1:
        num_people = (num_people > 0) ? num_people - 1 : 0;
        break;
    case 2:
        num_people = num_people + 1;
        break;
    }
#else
    num_people = newval;
#endif

    Serial.print("People in the room: ");
    Serial.println(num_people);

    // FIXME -- why clear both instead of just one (e.g. sens->sens_flag)???
    s1->sens_flag = 0;
    s2->sens_flag = 0;

    delay(DEBOUNCE_MS);
}

void
loop(void)
{

    sensread(s1);
    sensread(s2);

#if 0
    Serial.print("LDR 1: ");
    Serial.print(s1->s1_val);
    Serial.print("\t LDR 2: ");
    Serial.println(s2->sens_val);
    delay(200);
#endif

    // Someone goes in
    if (sensif(1,0,0))
        s2->sens_flag = 1;

    if (sensif(0,0,1)) {
        senswait(s2,num_people + 1);
        if (num_people == 1) {
            irsend.sendSony(IR_KEY, 20);
            Serial.println("BLING!");
        }
    }

    // Someone goes out
    if (sensif(0,0,0))
        s1->sens_flag = 1;

    if (sensif(1,1,0)) {
        senswait(s1,(num_people > 0) ? num_people - 1 : 0);
        if (num_people == 0) {
            irsend.sendSony(IR_KEY, 20);
            Serial.println("BLING!");
        }
    }
}
1 голос
/ 17 апреля 2020

Если я прав, ваш синтаксис для троичного оператора неправильный, должен быть таким:

(condition) ? (if_true) : (if_false)

Так должно быть так:

num_people > 0 ? num_people-- : num_people = 0;

То же, что и :

if (num_people > 0)
{
 num_people--;
}
else
{
 num_people = 0;
}

Если вы хотите использовать функцию, почему бы не сделать это?

void MyFuntion(uint16_t& SensVal, uint8_t const MinSensVal, uint8_t& NumPeople)
{
  timeout = millis() + MAX_TIME;
  while (SensVal > MinSensVal && (millis() > timeout));
  NumPeople++;
  Serial.print("People in the room: ");
  Serial.println(num_people);
}

Вам не нужно помещать все в функцию, только код, который имеет такой же структура.

...