Разработка библиотеки
- Войдите на сайт для отправки комментариев
Сб, 31/10/2020 - 20:20
Здравствуйте.
Хочу вынести функции обработки команд оn модуля SIM800 в отдельную библиотеку
#include <SoftwareSerial.h>
#include <Sim800L.h>
SoftwareSerial SIM800(9,10);// RX, TX
void setup() {
SIM800.begin(19200);
Serial.begin(19200);
Serial.println("Zagruzka");
}
void loop() {
if(SIM800.available()) Sim800L Otvet(SIM800.readString());
}
/*
Sim800L.h - Заголовочный файл
*/
#ifndef _Sim800L_H_
#define _Sim800L_H_
#include <Arduino.h>
class Sim800L
{
public:
Sim800L(String Otvet);
};
#endif
/*
Sim800L.cpp - Файл реализации
*/
#include "Sim800L.h"
Sim800L::Sim800L(String Otvet)
{
Otvet.trim();
Serial.println("Otvet: "+Otvet);
}
Верна ли логика?
Нет. Правильная логика - взять готовую библиотеку, а свое время потратить продуктивно.
Какую готовую? У меня свои функции в библиотеке будут.
Меня интересует логика работы библиотеки, разработка библиотеки
Наверно должно быть так:
SoftwareSerial SimPort(9, 10); // RX, TX
SIM800 mySim(SimPort);
Примитивненько, но работает
http://arduino.ru/forum/apparatnye-voprosy/vse-o-sim800l-i-vse-chto-s-ni...
а я по моему по твоей подсказке в допиленный SomeSerial CustomSoftwareSerial обернул, надо было обязательно выставить 8N2 для порта, работает как швейцарские часы, даже на одно прерывание с портом энкодер повесил для экспериментов
ЗЫ Иринка, иди мужу рогалики пеки, основа библиотеки уже есть, даже больше, на сегодня план выполнен )))
Спасибо, Буду разбираться.
Это не к логике, но всё-таки, вместо
пишите
Намного лучше в данном случае.
Спасибо, Буду разбираться.
а даташитом каким на модуль пользуетесь, из подвернувшихся не увидел ничего по работе с компортом, а там он физически полный
Здравствуйте. Проверить работу кода не могу, нет под рукой устройств, поэтому немного теоретических вопросиков.
Скетч
#include "Modem.h" #define MAX_BUF_SIZE 50 Modem SIM800(MAX_BUF_SIZE); void setup() { Serial.begin(9600); Serial.println("Start"); } void loop() {}Modem.h
//Modem.h #pragma once #include <Arduino.h> class Modem { public: Modem (uint8_t max_buf_size); void Reading(uint8_t temp); private: void clear_buffer(); uint8_t _max_buf_size; uint8_t _pos_buf; char _buffers[50]; };//Modem.cpp #include "Modem.h" Modem::Modem(uint8_t max_buf_size = 50) { _max_buf_size = max_buf_size; } void Modem::clear_buffer() { memset(_buffers, 0, _max_buf_size); _pos_buf = 0; } void Modem::Reading(uint8_t temp) { if (_pos_buf >= _max_buf_size) { clear_buffer(); } else { _buffers[_pos_buf] = temp; _pos_buf++; if (temp == '\n' && _pos_buf > 1 && _buffers[_pos_buf - 2] == '\r') { clear_buffer(); } } }Вопрос первый:
Код Modem.cpp 17 и 25 строки, верное обращение к функции? или Modem::clear_buffer()
Второй вопрос:
Modem.h переменная char _buffers[50]; Вместо значения 50 должна быть переменная.
В private объявлять пустой массив
private: char _buffers[];а в конструкторе устанавливать размер?
Modem::Modem(uint8_t max_buf_size = 50) { _max_buf_size = max_buf_size; _buffers[_max_buf_size]; }Я конечно не спец по C++, но основная функция конструктора именно выделерие памяти и инициализация переменных/объектов.
ЗЫ. Тяжела женская логика, вопроса на понял (
Я прочитала что размер массива должен быть известен до начала выполнения программы
Первый, вопрос - да, верное
Второй вопрос в привате объявляете указатель на массив, а в конструкторе выделяете под массив память
Как делать можно глянуть в этой теме - https://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/problemka-s-d...
Я прочитала что размер массива должен быть известен до начала выполнения программы
Всё зависит от задачи и от МК, например :
Если места нет как в avr для крупной обработки, выделяем крошечный буфер байт сто и в нем работаем, типичный пример можете посмотреть библиотеку ethernet 2, там буфер байт 30 и его заполняют и online отправляют.
Другой пример из последнего : ioLibrary от wiznet, там в http server разработчики вообще не парились, через alloc выделяют памяти в размер страницы http,есть у вас пару тройку килобайт, столько и нарисуют.
private: char* _buffers = NULL; Modem::Modem(uint8_t max_buf_size = 50) { _max_buf_size = max_buf_size; _buffers = new char(max_buf_size); }Так?
Irinka, вопрос: те кто теоретически будут использовать вашу библиотеку должны мозг включать чтоб знать сколько байт долно быть в буфере?
Если делаете для себя то и пропишите жёстко количество.
Ну а если универсальное - то сами должны определить количество.
MAX_BUF_SIZE часто меняться будет? В зависимости от чего?
всё, сгорели котлеты )))
Библиотеку буду использовать только я сама. С размером буфера возник вопрос, только потому что хочу понять как задать размер массива при создании объекта
всё, сгорели котлеты )))
А я то чего, я то ничего. Какие котлеты в 22 часа? (по МСК)
Нет, но хочу знать как задать размер массива при создании объекта
При создании - константой. В рантайме malloc-ом (он же new).
Библиотеку буду использовать только я сама. С размером буфера возник вопрос, только потому что хочу понять как задать размер массива при создании объекта
Всё зависит от логики работы, в примерах выше мне 16 байт хватало на все,. Дело вкуса...
Вот смотрите
class Modem { public: Modem (uint8_t max_buf_size); void Reading(uint8_t temp); void counts(); private: void clear_buffer(); uint8_t _max_buf_size; uint8_t _pos_buf; char* _buffers = NULL; };Modem::Modem(uint8_t max_buf_size = 50) { _max_buf_size = max_buf_size; //_buffers = new char(max_buf_size); _buffers = (char *)calloc(5, sizeof(char)); } void Modem::counts() { Serial.println(_max_buf_size); Serial.println(sizeof(_buffers) / sizeof(_buffers[0])); }#define MAX_BUF_SIZE 40 Modem SIM800(MAX_BUF_SIZE); void setup() { Serial.begin(9600); Serial.println("Start"); SIM800.counts(); //Получаю 40 //Получаю 2 } void loop() {}В протеусе проект накидала с ардуинкой)
всё, сгорели котлеты )))
А я то чего, я то ничего. Какие котлеты в 22 часа? (по МСК)
я о перпективе...шучу конечно...
private: char* _buffers = NULL; Modem::Modem(uint8_t max_buf_size = 50) { _max_buf_size = max_buf_size; _buffers = new char(max_buf_size); }Так?
Да
Тогда я получаю
SIM800.counts();
Получаю 40
Получаю 2
Код выше
Строка 04
_buffers = (char *)calloc(max_buf_size, sizeof(char));
Ну как бэ немножко-то думать нужно ))
SIM800.counts();
Получаю 40
Получаю 2
Код выше
Работа с указателями не эквивалентна работе с массивами. Указатель ничего "не знает" о размерности массива, он просто хранит адрес его первого элемента.
_buffers = (char *)calloc(5, sizeof(char));
У меня так и есть, просто поставила размер 5)
А получаю в мониторе
40
2
То есть размер массива у меня задаётся верно?
Если я ставлю размер изначально char _buffers[25] то получаю
25
25
Вам нужно понимать, что когда память выделяется статически через buffers[25], компилятор (!) может учесть эту размерность и правильно ей оперировать, проверяя выход за границы массива, вычисление sizeof и т.п. В случае со всякими *alloc, компилятор в процессе не участвует, так как все уже превращено в инструкции процессора, а *alloc выполняется как и другой пользовательский код. Программисту (!) следует самому озаботиться хранением размерности фрагмента выделенной памяти и проверкой на всякие записи "не туда".
Одним словом - если буфер статичен всегда, не нужно извращаться с указателями, особенно - если пока не понимаете их механики. Задайте размер массива через константу и позвольте компилятору делать то, что он умеет лучше. Всяким там маллокам место в других ситуациях. Например, когда нужно только иногда организовывать такой буфер попеременно используя один и тот же фрагмент памяти то для формирования JSON, который будет отдан в сеть, то для строки вывода на LCD.
Хорошо. Спасибо)
Здравствуйте.
Подскажите
Buttons.h
//Buttons.h #pragma once #include <Arduino.h> class Buttons { public: Buttons (uint8_t pin); bool pressing() { bool pinstat = digitalRead(_pin); return pinstat; }; private: uint8_t _pin; };Buttons.cpp
//Buttons.cpp #include "Buttons.h" Buttons::Buttons(uint8_t pin) { _pin = pin; pinMode(_pin, INPUT); }Если я объявляю в классе bool pressing();
class Buttons { public: Buttons (uint8_t pin); bool pressing(); private: uint8_t _pin; };То в Buttons.cpp компилятор ругается на Buttons::pressing() {
prototype for 'int Buttons::pressing()' does not match any in class 'Buttons
Разобралась...
bool Buttons::pressing() { bool pinstat = digitalRead(_pin); return pinstat; };Разобралась...
bool Buttons::pressing() { bool pinstat = digitalRead(_pin); return pinstat; };за 4-ре минуты, похвально...
Ахах, а как же время написания ответа?))) Минусуйте! Максимум 1,7 минуты! XDDD
Скетч
#include "Buttons.h" Buttons bu1(2); Buttons bu2(3); void setup() { Serial.begin(9600); Serial.println("Start"); } void loop() { if (bu1.pressing())Serial.println("bu1 > 500"); if (bu2.pressing())Serial.println("bu2 > 500"); }Buttons.h
//Buttons.h #pragma once #include <Arduino.h> class Buttons { public: Buttons (uint8_t pin); bool pressing(); private: uint8_t _pin; uint32_t _tmr; uint8_t _stat; };Buttons.cpp
//Buttons.cpp #include "Buttons.h" Buttons::Buttons(uint8_t pin) { _pin = pin; _stat = 0x00; pinMode(_pin, INPUT); } bool Buttons::pressing() { bool pinstat = digitalRead(_pin); bool stat_ret = false; switch (_stat) { case 0x00: if (pinstat)_stat = 0x01; break; case 0x01: if (!pinstat ) { _tmr = millis(); _stat = 0x02; } break; case 0x02: if (!pinstat) { if (millis() - _tmr >= 500) { _stat = 0x00; stat_ret = true; } } else { _tmr = millis(); } break; } return stat_ret; };Задача: отследить изменение состояния кнопки с 1 на 0 плюс дребезг 500 мс
Верна логика? Или намудрила?
дребезг полсекунды - это через край, обычно 50 мс достаточно
что касается логики - могу посоветовать нарисовать блок-схему - так будет наглядно видно, что да как. А по блок-схеме уже и код писать ))
Ахах, а как же время написания ответа?))) Минусуйте! Максимум 1,7 минуты! XDDD
всё таки минута 48 секунд )))
дребезг полсекунды - это через край, обычно 50 мс достаточно
что касается логики - могу посоветовать нарисовать блок-схему - так будет наглядно видно, что да как. А по блок-схеме уже и код писать ))
Больше подходит слово удержание, чем дребезг)
Ахах, а как же время написания ответа?))) Минусуйте! Максимум 1,7 минуты! XDDD
всё таки минута 48 секунд )))
Agree)
дребезг полсекунды - это через край, обычно 50 мс достаточно
что касается логики - могу посоветовать нарисовать блок-схему - так будет наглядно видно, что да как. А по блок-схеме уже и код писать ))
Больше подходит слово удержание, чем дребезг)
Это разные понятия )) Дребезг нужно отсеивать в любом случае
В общем случае нужна одна функция, которая постоянно мониторит состояние кнопки и по изменениям выставляет события/флаги событий. Это если нужно отслеживать разные события кнопки - нажата, отпущена, удерживается и т.д.
Ну тут и получается как антидребезг, поставить время 50 мс
Примерный алгоритм
Если поднят флаг антидребезга, то Если интервал антидребезга еще не прошел, то ничего не делать, иначе - опустить флаг антидребезга - выдать событие нажатия/отпускания кнопки в зависимости от текущего состояния ее контактов - сохранить текущее состояние кнопки Если флаг антидребезга не поднят, то Если текущее состояние кнопки равно сохраненному, то ничего не делать, иначе - поднять флаг антидребезга - запустить таймер антидребезгаКак-то так
Если нужно отслеживать еще и удержание кнопки, то алгоритм немного усложняется
Если поднят флаг антидребезга, то Если интервал антидребезга еще не прошел, то ничего не делать, иначе - опустить флаг антидребезга - выдать событие нажатия/отпускания кнопки в зависимости от текущего состояния ее контактов - сохранить текущее состояние кнопки Если флаг антидребезга не поднят, то Если текущее состояние кнопки не равно сохраненному, то - поднять флаг антидребезга - запустить таймер антидребезга Если текущее состояние кнопки равно сохраненному, и кнопка нажата, то Если интервал удержания прошел (можно использовать таймер антидребезга, тогда удержание будет отсчитываться от момента первого касания контактов кнопки) - выдать событие удержания кнопки нажатойСобытие удержания будет выдаваться все время, пока кнопка удерживается нажатой. Если нужно однократное событие удержания, то придется заводить еще один флаг - удержания кнопки и выдавать событие только если флаг еще не поднят (и тут же его поднимать). И сбрасывать этот флаг в момент отпускания кнопки ))
В общем, без
поллитрыблок-схемы мозг сломать можно )))Ну тут и получается как антидребезг, поставить время 50 мс
зависит от кнопок, для моих от 70 до 120 миллисекунд
https://github.com/kakmyc-github/kakmyc_btn
И не парюсь уже пару лет. ))