Отправка данных на thingspeak

lengast
Offline
Зарегистрирован: 17.08.2019

Здравствуйте.
Мне необходимо отслеживать состояние 2х датчиков и при срабатывании отправлять время срабокти на thingspeak.
Но записать данные получается очень редко. На 30 попыток может произойти 1 передача.
Передача данных проивзодится по GPRS используя GPRS-shield от Амперки, на борту которого SIM800C.
При запуск модуль включается, получает IP сети. Настройки интернета выставлены верно.
Прошу подсказать где я допустил ошибку.
Мучаюсь уже 2й день, буду признателен за любой совет.
Код прилогаю ниже:
 

Moderator : пожалуйста, вставьте код правильно - http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii
b707
Offline
Зарегистрирован: 26.05.2017

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

lengast
Offline
Зарегистрирован: 17.08.2019
#include <TroykaRTC.h>
#include <GPRS_Shield_Arduino.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#define SIM900_TX_PIN 4
#define SIM900_RX_PIN 5
#define SIM900_POWER_PIN 9
#define SIM900_BAND 9600
#define SENSOR_1_PIN 2
#define SENSOR_2_PIN 8
#define MIN_SEND_INTERVAL 22    // Максимальная частота отправки запросов на сайт (ограничение thingspeak)
#define SENSOR_ACTIVE_STATE HIGH //Состояние выхода датчика при сработке
#define H08M00_H19M30 15    // Интервал 08:00-19:30
#define H19M30_H22M30 15    // Интервал 19:31-22:30
#define H22M30_H06M00 60    // Интервал 22:31-06:00
#define H06M00_H08M00 15    // Интервал 06:01-07:59
RTC clock;
String time;
String date;
String weekDay;
// Адрес сайта (не менять)
char gprs_server[] = "api.thingspeak.com";
 
// Ключ для записи на сайт 
String API = "***KWQ1DU3A5KBJE";
 
// ВАШ НОМЕР ТЕЛЕФОНА ДЛЯ ЗВОНКОВ
char phone[] = "+79****";
 
//Служебные флаги
bool vypis = 0;
bool need_send_info_1 = false;
bool need_send_info_2 = false;
bool check1 = false;
bool check2 = false;
bool Sensor1State = false;
bool lastSensor1State = false;
int SensorCounter1 = 0;
bool Sensor2State = false;
bool lastSensor2State = false;
int SensorCounter2 = 0;
 
// Переменная, которая хранит максимальное время между сработками (если за это время датчик не сработал, будет звонок)
unsigned long max_send_interval = 900;
 
// Временная метка последнего звонка
unsigned long timestamp_call = 0;
 
// Служебные флаги
bool need_calling = false;
bool block_calling = false;
 
 
GPRS sim900(SIM900_TX_PIN, SIM900_RX_PIN, SIM900_BAND);
 
void send_info()
{
    static unsigned long send_timestamp = millis();
 
    // Проверка, что шлем не слишком часто и что надо отправлять
    if ((millis() - send_timestamp > MIN_SEND_INTERVAL * 1000) & (need_send_info_1 || need_send_info_2))
    {
        Serial.print("TIMESTAMP ");
        Serial.println(send_timestamp);
        if (!sim900.connect(TCP, gprs_server, 80)) 
        {
            Serial.println("Connect to server error");
            delay(5000);
        }
        else 
        {
            Serial.print("-> Connect to ");
            Serial.print(gprs_server);
            Serial.println(" OK!");
            String url = "GET /update?api_key=";
            Serial.println(url);
            url += API;
            if (need_send_info_1 && need_send_info_2)
            {
                url += "&field1=1";
                url += "&field2=1";              
            }
            else if (need_send_info_1)
            {
                url += "&field1=1";
            }
            else if (need_send_info_2)
            {
                url += "&field2=1";
            }
            else
            {
                return;
            }
            url += " HTTP/1.0\r\n\r\n";
            char urlChar[url.length() + 1];
            url.toCharArray(urlChar, url.length() + 1);
            sim900.send(urlChar, url.length());
            char odpoved[512];           
            while (true) 
            {             
                int znaky = sim900.recv(odpoved, sizeof(odpoved) - 1);
                if (znaky <= 0) 
                {
                    if (vypis) 
                    {
                        Serial.println("-> End answer.");
                    }
                    break;
                }
                odpoved[znaky] = '\0';
                if (vypis) 
                {
                    Serial.print("Get: ");
                    Serial.print(znaky);
                    Serial.print(" byte: ");
                    Serial.println(odpoved);
                }
            }
            sim900.close();
            sim900.disconnect();
            if (need_send_info_1 && need_send_info_2)
            {
                need_send_info_1 = false;
                need_send_info_2 = false;
                timestamp_call = millis();
                block_calling = false;
            }
            else if (need_send_info_1)
            {
                need_send_info_1 = false;
                timestamp_call = millis();
                block_calling = false;
            }
            else if (need_send_info_2)
            {
                need_send_info_2 = false;
            }
            send_timestamp = millis();
            Serial.println("-> Disconnect");
            
        }
       
    }
    
}
 
 
// Звонок на телефон
void calling()
{
    static unsigned long timestamp = 0;
    static bool is_calling = false;
    if (need_calling)
    {
        if (millis() - timestamp > 20000 && !is_calling && !sim900.isCallActive(phone) && !block_calling)
        {
            sim900.callUp(phone);
            is_calling = true;
            timestamp = millis();
        }
        else if (millis() - timestamp > 20000 && is_calling && !sim900.isCallActive(phone))
        {
            block_calling = true;
            timestamp = millis();
            is_calling = false;
        }
        else if (millis() - timestamp > 20000 && is_calling && sim900.isCallActive(phone))
        {
            timestamp = millis();
            is_calling = false;
            sim900.hangup();
        }
    }
}
 
// Проверка времени
void check_time()
{
    clock.read();
    clock.getTimeStamp(time, date, weekDay);
    int hours = 0;
    int minutes = 0;
    hours = time.substring(0,2).toInt();
    Serial.println(time.substring(0,2));
    Serial.println(time.substring(3,5));
    Serial.println(time.substring(6,8));
    minutes = time.substring(3,5).toInt();
  
    // Интервал 08:00-19:30
    if (hours >= 8 && hours <= 19)                 // Сначала смотрим, что попали по часам
    {
        if (hours == 19 && minutes <=30)           // Проверяем верхний предел по минутам
        {
            max_send_interval = H08M00_H19M30*60;
        }
        else if (hours >= 8 && hours < 19)         // Смотрим широкий интервал
        {
            max_send_interval = H08M00_H19M30*60;
        }
    }
 
    // Интервал 19:31-22:30
    if (hours >= 19 && hours <= 22)                 // Сначала смотрим, что попали по часам
    {
        if (hours == 19 && minutes > 30)            // Проверяем в нижний предел по минутам
        {
            max_send_interval = H19M30_H22M30*60;
        }
        else if (hours == 22 && minutes <=30)       // Проверяем верхний предел по минутам
        {
            max_send_interval = H19M30_H22M30*60;
        }
        else if (hours > 19 && hours < 22)          // Смотрим широкий интервал
        {
            max_send_interval = H19M30_H22M30*60;
        }
    }
 
    // Интервал 22:31-6:00
    if (hours >= 22 || hours <= 6)
    {
        if (hours == 22 && minutes > 30)
        {
            max_send_interval = H22M30_H06M00*60;
        }
        else if (hours == 6 && minutes == 00)
        {
            max_send_interval = H22M30_H06M00*60;
        }
        else if (hours >= 22 || hours <= 6)
        {
            max_send_interval = H22M30_H06M00*60;
        }
    }
    
    // Интервал 6:01-8:00
    if (hours >= 6 && hours <= 8)
    {
        if (hours == 6 && minutes > 1)
        {
            max_send_interval = H06M00_H08M00*60;
        }
        else if (hours == 8 && minutes == 00)
        {
            max_send_interval = H06M00_H08M00*60;
        }
        else if (hours > 6 && hours < 8)
        {
            max_send_interval = H06M00_H08M00*60;
        }
    }
    Serial.print("h="); Serial.print(hours);Serial.print("m=");Serial.print(minutes);Serial.print("max_send_interval");Serial.println(max_send_interval);
    
}
 
void setup() 
{
    Serial.begin(9600); // Скорость обмена данными с компьютером
    clock.begin();
   // clock.set(__TIMESTAMP__);
    pinMode(SENSOR_1_PIN, INPUT_PULLUP);
    pinMode(SENSOR_2_PIN, INPUT_PULLUP);
    
    if (!sim900.checkPowerUp()) 
    {
        sim900.powerUpDown(SIM900_POWER_PIN);
    }
    
    Serial.print("SIM900 INIT");
    while (!sim900.init()) 
    {
        Serial.print(".");
        delay(1000);
    }
    delay(5000);
    Serial.println("OK");
    
    Serial.print("Setting GPRS");
    // Настройки интернета
     while (!sim900.join(F("beeline.internet.ru"), F("beeline"), F("beeline")))  
    {
        Serial.print(".");
        delay(2000);
    }
    Serial.print("OK");
    
    Serial.print("IP Adress: ");
    Serial.println(sim900.getIPAddress());
    check_time();
}
 
void loop() 
{
    static unsigned long time_update_stamp = 0;
    //датчик 1//
    Sensor1State = digitalRead(SENSOR_1_PIN);
    if (Sensor1State != lastSensor1State) {
        if (Sensor1State == LOW) {
          check1 = HIGH;
          Serial.println("on sens1");
          delay(25);
        }
        else {
          check1 = LOW; 
        }
        delay(25);
        Serial.println(check1);
        }
  lastSensor1State = Sensor1State;
  
  if (check1 == HIGH) {
      need_send_info_1 = true;
      Serial.println("Сработал датчик 1");
      Serial.println(need_send_info_1);
      delay(50);
      } 
  else 
       
    //датчик 2//
  Sensor2State = digitalRead(SENSOR_2_PIN);
  if (Sensor2State != lastSensor2State) {
    if (Sensor2State == LOW) {
      check2 = HIGH;
      Serial.println("on sens2");
      delay(50);
    }
    else {
      check2 = LOW; 
    }
    delay(50);
    Serial.println(check2);
  }
  lastSensor2State = Sensor2State;
  if (check2 == HIGH) {
    need_send_info_2 = true;
    Serial.println("Сработал датчик 2");
    Serial.println(need_send_info_2);
  } 
    // Проверяем и если надо отправляем данные 
    send_info();
 
    // Если превышен предел максимального времени сработки ставим флаг, что надо звонить
    if (millis() - timestamp_call > max_send_interval * 1000 && !block_calling)
    {
        need_calling = true;
    }
    else
    {
        need_calling = false;
    }
 
    // Делаем звонок
    calling();
 
    // Обновляем данные о значении максимального времени сработки каждую минуту в зависимости от времени
    if (millis() - time_update_stamp > 60000)
    {
        check_time();
        time_update_stamp = millis();
    }
 
    // Чтобы дать время подумать
    delay(300);
}

 

b707
Offline
Зарегистрирован: 26.05.2017

неужели даже после подсказки не нашли? - строка 61

lengast
Offline
Зарегистрирован: 17.08.2019

Ошибку нашел, исправил. Но проблема не делать. 
Диагностируя состояние переменных через Serial обнаружил, что операции объединения строк в функции "send_info" не производятся. В чем может быть проблема?

b707
Offline
Зарегистрирован: 26.05.2017

может не ту ошибку исправили?

Dmti
Dmti аватар
Offline
Зарегистрирован: 13.10.2013

Если не формируется url, то выведите на экран переменные в условиях, и посмотрите какие условия у вас сработают.

lengast
Offline
Зарегистрирован: 17.08.2019

В условии нехватало одного "&". Верно ?
 

lengast
Offline
Зарегистрирован: 17.08.2019

Так и делаю. Условия срабатывают верно, но url не формируется.
Если объявить url без контактенации, то он отобразиться, но дальнейшие манипуляции с ним ни к чему не приводят

Dmti
Dmti аватар
Offline
Зарегистрирован: 13.10.2013

if ((millis() - send_timestamp > MIN_SEND_INTERVAL * 1000) & (need_send_info_1 || need_send_info_2))

Вы сдесь проверяете три разных условия или пытаетесь произвести булевую операцию?

b707
Offline
Зарегистрирован: 26.05.2017

lengast пишет:

 Условия срабатывают верно, но url не формируется.

Так не бывает.

вставьте вывод url в Сериал после каждой конкатеации и покажите результат

lengast
Offline
Зарегистрирован: 17.08.2019

Проблема решена. Использовал макрос F() для вывода диагностических сообщений в порт и перенес объявление переменной в основной цикл.
Видимо происходило переполнение памяти и неверная запись.