В целом, микроконтреллер должен выполнять все алгоритмы сам, без участия компьютера, а компьютер необходим лишь для визуального контроля и ручного управления. Собственно перекладывать функцию опроса датчиков на сам датчик, не особо практично. При условии, что в квартире будет 10-20 датчиков, и уже вшитых в стены, на сколько практично будет их перепрограммировать на новые адреса сервера? Или после изменения свойств в таблице баз данных, не проще переписать скрипт на сервере, чем каждый отдельный датчик. Нужна универсальность и масштабируемость, но если эти данные писать в железку, то ничего этого не будет.
Что-то я запутался в Ваших рассуждениях :)
Дуня сама посылает данные на сервер.
Поменялся адрес сервера? Как часто он у Вас меняется? И старый насовсем пропадает?
А если датчик выйдет из строя, что по моему гораздо реальнее чем смена сервера :)?
Изменение свойств в таблице баз данных???? Кхм... Вы напряму в БД пишите нативным драйвером?
Нафига? Если цель - положить показания датчика в базу? Зачем еще что-то отвечать, городить парсинг ответа на ардуине и т.п.? Послали данные - и все. Ну максимум проверили что http 200 вернулся (если нет - зажгли какую-то красную аварийную лампочку). И то... уже "по желанию".
Поднимать на Дуне клиента и сервер? Или как мы будем с телефона лампочкой мигать?
Холивар на тему как лучше и хуже, считаю пустым. Если JollyBiber считает что обратная связка лучше, то я с ним и соглашусь, но реализация при опросе датчиков сервером, мне больше по душе. Leshak, по контексту я догадался, и не более, что при запросе/обновлении страницы, данные должны обновляться. Но к сожалению этого не происходит. Я постоянно нажимаю F5 + сервер отправлет запрос через php скрипт, что равнозначно обновлению страницы, но данные не меняются. Хотя датчик нагреваю зажигалкой. И только после перезагрузки arduino данные обновляются. Не знаю почему так. Если кто-то может подсказать, скажите в чем дело. Код на всякий слуйчай еще рах прикреплю:
/**
* Контроллер-исполнительное устройство (к проекту http://smartliving.ru/)
* Platform: Arduino UNO R3 + EthernetShield W5100
* IDE: Arduino 1.0.1
*
* исполнительные устройства (реле) подключены к Digital 3 - 9
*
* обращение по http://xx.xx.xx.xx/ выдаст справочную информацию по этому устройству (нужно для того, чтобы когда обращаешься
* по IP к устройству понять что это за контроллер и пр.)
*
* /state - состояние всех портов
* /command - выполнение команды
* команды можно вызывать серией в 1 запросе. Например http://xx.xx.xx.xx/command?3=CLICK&4=CLICK&5=ON&6=OFF
* только длинна строки запроса не должна привышать maxLength
* /getdev - получить список всех устройст на 1-wire
* формат вывода:
* T<номер устройства на шине>:<HEX адрес устройства>:<текущая температура в градусах цельсия>;[...]
* (пример T0:1060CF59010800E3:24.06;T1:109ABE59010800FE:24.56;)
*
**/
#include <Ethernet.h>
#include <SPI.h>
#include <Arduino.h>
#include "WebServer.h" // Webduino (https://github.com/sirleech/Webduino)
#include <OneWire.h>
#include <DallasTemperature.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE4, 0xDE, 0x35 }; // MAC-адрес нашего устройства
byte ip[] = { 192, 168, 0, 210 };
byte subnet[] = { 255, 255, 255, 0 };
byte gateway[] = { 192, 168, 0, 1 };
byte dns_server[] = { 192, 168, 0, 1 };
// ip-адрес удалённого сервера
byte rserver[] = { 192, 168, 0, 78 };
// Настройки выходов
int startPin=3;
int endPin=9;
// Pin controller for connection data pin DS18S20
#define ONE_WIRE_BUS 2 // Digital 2 pin Arduino (куда подключен выход с шины датчиков DS18X20
#define TEMPERATURE_PRECISION 9
#define VERSION_STRING "0.1"
#define COMPILE_DATE_STRING "2012-09-18"
P(Page_info) = "<html><head><title>smartliving.ru controller " VERSION_STRING "</title></head><body>\n";
P(location_info) = "underground server room";
P(pin_info) = "D2 - 1-wire (many DS18S20)<br>D3-light undergroung";
P(version_info) = VERSION_STRING ". Compile date: " COMPILE_DATE_STRING;
String url = String(25);
int maxLength=25; // Максимальная длинна строки запроса
#define delayClick 1000 // задержка при обычном CLICK
#define delayLClick 3000 // задержка при длинном LCLICK
#define MAX_COMMAND_LEN (10)
#define MAX_PARAMETER_LEN (10)
#define COMMAND_TABLE_SIZE (8)
#define PREFIX ""
WebServer webserver(PREFIX, 80);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// Для поиска
DeviceAddress Termometers;
float tempC;
#define NAMELEN 32
#define VALUELEN 32
char gCommandBuffer[MAX_COMMAND_LEN + 1];
char gParamBuffer[MAX_PARAMETER_LEN + 1];
long gParamValue;
typedef struct {
char const *name;
void (*function)(WebServer &server);
} command_t;
command_t const gCommandTable[COMMAND_TABLE_SIZE] = {
// {"LED", commandsLed, },
{"HELP", commandsHelp, }, // Выводит список комманд (вызов http://xx.xx.xx.xx/command?8=HELP )
{"ON", commandsOn, }, // Устанавливает "1" на заданном цифровом порту (вызов http://xx.xx.xx.xx/command?8=ON )
{"OFF", commandsOff, }, // Устанавливает "0" на заданном цифровом порту (вызов http://xx.xx.xx.xx/command?8=OFF )
{"STATUS", commandsStatus, }, // Получить состояние цифрового порта (1 или 0) (вызов http://xx.xx.xx.xx/command?8=STATUS ),
// если вместо номера порта передать ALL (вызов http://xx.xx.xx.xx/command?ALL=STATUS ), то получим состояние всех портов (Пример вывода P3=0;P4=0;P5=0;P6=0;P7=0;P8=1;P9=1;)
{"CLICK", commandsClick, }, // Кратковременная "1" на порту 1сек (время настраивается) (вызов http://xx.xx.xx.xx/command?8=CLICK )
{"LCLICK", commandsLClick, }, // Кратковременная "1" на порту 3сек (время настраивается) (вызов http://xx.xx.xx.xx/command?8=LCLICK )
{NULL, NULL }
};
/**********************************************************************************************************************
*
* Function: cliProcessCommand
*
* Description: Look up the command in the command table. If the
* command is found, call the command's function. If the
* command is not found, output an error message.
*
* Notes:
*
* Returns: None.
*
**********************************************************************/
void cliProcessCommand(WebServer &server)
{
int bCommandFound = false;
int idx;
gParamValue = strtol(gParamBuffer, NULL, 0); // Convert the parameter to an integer value. If the parameter is empty, gParamValue becomes 0.
for (idx = 0; gCommandTable[idx].name != NULL; idx++) { // Search for the command in the command table until it is found or the end of the table is reached. If the command is found, break out of the loop.
if (strcmp(gCommandTable[idx].name, gCommandBuffer) == 0) {
bCommandFound = true;
break;
}
}
if (bCommandFound == true) { // Если команда найдена (в массиве команд), то выполняем ее. Если нет - игнорируем
(*gCommandTable[idx].function)(server);
}
else { // Command not found
server.print("ERROR: Command not found");
}
}
/**********************************************************************************************************************/
/* Обработчики команд */
void commandsOn(WebServer &server) {
if (gParamValue>=startPin && gParamValue<=endPin) {
digitalWrite(gParamValue,HIGH);
} else ErrorMessage(server);
}
void commandsOff(WebServer &server) {
if (gParamValue>=startPin && gParamValue<=endPin) {
digitalWrite(gParamValue,LOW);
} else ErrorMessage(server);
}
void commandsClick(WebServer &server) {
if (gParamValue>=startPin && gParamValue<=endPin) {
digitalWrite(gParamValue,HIGH);
delay(delayClick);
digitalWrite(gParamValue,LOW);
} else ErrorMessage(server);
}
void commandsLClick(WebServer &server) {
if (gParamValue>=startPin && gParamValue<=endPin) {
digitalWrite(gParamValue,HIGH);
delay(delayLClick);
digitalWrite(gParamValue,LOW);
} else ErrorMessage(server);
}
void commandsStatus(WebServer &server) {
if (strcmp(gParamBuffer, "ALL") == 0) { // выдать состояние всех пинов
for(int i=startPin;i<=endPin;i++) {
int st=digitalRead(i);
char my_st[5];
itoa(st,my_st,10);
server.print("P");
server.print(i);
server.print("=");
server.print(my_st);
server.print(";");
}
} else { // выдать состояние только 1 пина
if (gParamValue>=startPin && gParamValue<=endPin) {
server.print("P");
server.print(gParamValue);
server.print("=");
server.print(digitalRead(gParamValue));
} else ErrorMessage(server);
}
}
void commandsHelp(WebServer &server) {
int idx;
for (idx = 0; gCommandTable[idx].name != NULL; idx++) {
server.print(gCommandTable[idx].name);
server.print("<br>");
}
}
/**********************************************************************************************************************/
void ErrorMessage(WebServer &server) {
server.print("ERROR: This Pin is not configured for I/O");
}
/**********************************************************************************************************************
* Разбор запроса
**/
void parsedRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
URLPARAM_RESULT rc;
char name[NAMELEN];
int name_len;
char value[VALUELEN];
int value_len;
server.httpSuccess(); // this line sends the standard "we're all OK" headers back to the browser
/* if we're handling a GET or POST, we can output our data here.
For a HEAD request, we just stop after outputting headers. */
if (type == WebServer::HEAD)
return;
if (strlen(url_tail))
{
while (strlen(url_tail)) // Разбор URI на составные части (выборка параметров)
{
rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
if (rc == URLPARAM_EOS) {
// server.printP(Params_end);
}
else // Получили параметр (name) и его значение (value)
{
// Выполняем команды
strcpy (gCommandBuffer, value); // параметры (значение)
strcpy (gParamBuffer, name); // команда
cliProcessCommand(server);
}
}
}
/*
if (type == WebServer::POST)
{
server.printP(Post_params_begin);
while (server.readPOSTparam(name, NAMELEN, value, VALUELEN))
{
server.print(name);
server.printP(Parsed_item_separator);
server.print(value);
server.printP(Tail_end);
}
}
*/
}
void get1wireDevices(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
//TODO получить все устройства на шине и выдать на страницу
int numberOfDevices = sensors.getDeviceCount();
sensors.begin();
for(int i=0;i<numberOfDevices; i++) {
if(sensors.getAddress(Termometers, i))
{
// server.print("T");
// server.print(i);
// server.print(":");
for (uint8_t i = 0; i < 8; i++) {
if (Termometers[i] < 16) server.print("0");
server.print(Termometers[i], HEX);
}
float tempC = sensors.getTempC(Termometers);
server.print(":");
server.print(tempC);
server.print(";");
} else {
// not found
server.print("NOT FOUND");
}
}
}
void stateRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
strcpy (gParamBuffer, "ALL");
commandsStatus(server);
}
/**********************************************************************************************************************
* Генерация и вывод информации об устройстве
**/
void infoRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
server.printP(Page_info);
server.print("IP:");
server.print(Ethernet.localIP());
server.print("<br>Location:");
server.printP(location_info);
server.print("<hr>Pin info:<br>");
server.printP(pin_info);
server.print("<hr>Pin current state: ");
strcpy (gParamBuffer, "ALL");
commandsStatus(server);
server.print("<hr><a href='/getdev'>1-wire devices</a>");
server.print("<hr>Commands:<br>");
commandsHelp(server);
server.print("<hr><br>Version info: ");
server.printP(version_info);
}
/**********************************************************************************************************************
* Поиск устройств (датчиков температуры на шине 1-wire)
**/
void searchDevices() {
Serial.print("Start search on 1-wire");
int numberOfDevices = sensors.getDeviceCount();
sensors.begin();
for(int i=0;i<numberOfDevices; i++) {
if(sensors.getAddress(Termometers, i))
{
Serial.print("Found device ");
Serial.print(i, DEC);
Serial.print(" with address: ");
for (uint8_t i = 0; i < 8; i++) {
if (Termometers[i] < 16) Serial.print("0");
Serial.print(Termometers[i], HEX);
}
Serial.print("Resolution actually set to: ");
Serial.print(sensors.getResolution(Termometers), DEC);
Serial.println();
float tempC = sensors.getTempC(Termometers);
Serial.print(tempC);
Serial.println("C");
} else {
// not found
}
}
}
/**********************************************************************************************************************/
void setup() {
// Для дебага будем выводить отладочные сообщения в консоль
//TODO Убрать вывод в консоль "за дабаг" (т.е. вывод только если скимпилированно с поддержкой дебага)
Serial.begin(9600);
Serial.println("Start");
Ethernet.begin(mac, ip, dns_server, gateway, subnet); // Инициализируем Ethernet Shield
webserver.setDefaultCommand(&infoRequest); // дефолтная страница вывода (информация о контроллере)
webserver.addCommand("command", &parsedRequest); // команды
webserver.addCommand("state", &stateRequest); // выдать состояния всех устройств
webserver.addCommand("getdev", &get1wireDevices); // получить список устройств на 1-wire
webserver.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
// Настройка портов на вывод
for (int thisPin = startPin; thisPin <=endPin; thisPin++) {
pinMode(thisPin, OUTPUT);
}
// Настройки 1-wire
sensors.begin(); // Инициализация шины 1-wire (для датчиков температуры)
sensors.requestTemperatures(); // Перед каждым получением температуры надо ее запросить
searchDevices();
}
/**********************************************************************************************************************/
void loop() {
//searchDevices();
//delay(60000);
char buff[64];
int len = 64;
webserver.processConnection(buff, &len); // process incoming connections one at a time forever
}
JollyBiber, даже сейчас это отстраивается на виртуальном сервере. В планах переносить это на физический. На этом сервере имеем web-морду c указанием в настройках IP адреса "Arduino". Arduino получает IP адрес по DHCP. На роутере, или DHCP серваке пробиваем по мак адресу или номеру устройства IP адрес железки и имеем полный доступ к ней, например такой как здесь: http://www.ab-log.ru/smart-house/ethernet/megad-panel И я считаю это более чем удобно. Все-же холивар на эту тему, не уместен в данном вопросе. Человеку нужно найти решение именно в решении его задачи, а не рассуждать как это лучше. Если оно действительно лучше, то это придет только с опытом и пониманием всего и вся. А в задаче ТС уже найдено решение, и спасибо данному форуму за это.
Divest, да развеж я против? Удобнее - так пользуйтесь на здоровье. Я прописал IP статически и ничего не пробиваю :) На вкус и цвет все фломастеры разные.
Осталось только опять применить принцип, не строить сразу космический корабль, вначале запчасти по одной проверить.
Вы, в режиме реального времени с датчика температуру научились получать? Без серверов и запросов. Обыкновенным serial.println() видеть как нагревание пальцами дает увеличение цифр в Serial Monitor-е?
Прежеде чем браться за отправку данных с ds1820 через шилды... может просто нужно корректно научится ее получать регулярно?
Какой библиотекой у вас происходит работа с датчиком? DallasTemperatureControll. А библиотека что имеет? Правильно. Примеры. Вот вначале нужно и убедится в их работе. Разобрать построчно "что деалает каждая строчка".
Ну а потом, будете смотреть, "в чем разница". Между содержимым loop() в примере и вашей get1wireDevices(... ) . Смотреть "чего же не хватает" (кстати выше - уже намекнули чего).
Я бы рекомендовал начать, как ни странно, с примера с именем "Simple". А все эти обнаружения отключения датчиков на ходу, работу с несколькими датчиками.... оставил бы на потом.
Кстати изначально-то getdev это команда получить список устройств. А не "получить температуру".
Заведите себе еще одну комманду. создайте, по аналогии функцию getTemp()
и добавте ее в спискок доступных комманд:
webserver.addCommand("gettemp", &getTemp);
И уже в нее пихайте куски из библиотечного примера (после того как запустите сам пример).
Leshak, Interkom, спаисбо большое. Leshak, у меня получилось простым примером определять температуру с датчиков, и делать опрос нескольких датчиков, по библиотеке OneWire. И можно сказать что я в целом разобрался. Но некоторые вещи просто вылетают у меня из виду. И да, вы больше чем правы, мне нужно больше изучать основы, чем пытаться брать наскоком. Будем курить мануалы.
Leshak, у меня получилось простым примером определять температуру с датчиков, и делать опрос нескольких датчиков, по библиотеке OneWire.
Зачем OneWire? Можно конечно "чистым OneWire", но ведь есть DallasTemperatureControll. Которая и есть обертка над OneWire. Для упрощения. Тем более что эта библиотека - у вас уже подключена.
Ну, вот теперь берете тот пример (предварительно построчно его осознав) .... заворачиваете в функцию которая вызывается по http запроcу, заменяете Serial.println, на server.print.....
Кстати можно не заменять, а рядышком их...
Что-бы одновременно и в Serial-мониторе видеть, и в браузере... В сериал мониторе смотреть "вот пришел запрос", "вот опросили датчик", "вот получили такую температуру", "вот отправили ответ браузеру...".
Что-бы легче понять "что там вообще происходит.
Кстати, спрошу возможно дурацкий вопрос (к сожалению не всегда), а вы вообще знаете где примеры "идущие с библиотекой смотреть"? Или "что нашлось в гугле то и пробуем"?
Leshak, надеялся что у "спецов" в данной теме не совсем уж такое мнение обо сложится. Примеры идут вместе с библиотеками. Либо через файл-примеры. Либо через папку с библиотекой, Examples. Странно, но библиотека DallasTemperature у меня идет с примерами в ArduinoTemperatureControlLibrary, качал с гита. 1-wire отдельно. Но там уже есть примеры и мне собственно они понятны.
Leshak, надеялся что у "спецов" в данной теме не совсем уж такое мнение обо сложится.
Вот тоже делать нечего... мнения складывать :) Если вы думаете что один раз приходилось рассказывать про такой волшебный источник примеров :)
Divest пишет:
Странно, но библиотека DallasTemperature у меня идет с примерами в ArduinoTemperatureControlLibrary,
Ничерта не понял. Возможно это намек на какой-то "конфликт библиотек".
Divest пишет:
качал с гита. 1-wire отдельно. Но там уже есть примеры и мне собственно они понятны.
Ну 1-wire - это само собой. Она нужна в любом случае. Просто это "универсальная библиотека" которая как-бы для любых датчиков которые используют эту шину. И нее в примерах, ds1820 идет, конечно как пример работы с датчиком, но... в силу ее универсальности - использовать 1-wire в сыром виде - не слишком удобно.
DallasTemperatureControl это уже обертка над OneWire. Для облегчения работы конкретно с этим датчиком. Еще один слой абстракции (но внутри, она сама, естественно OneWire использует).
Ну и, в конечном итоге, я так и не понял... получилось у вас или нет? Если "пример запустился" (в конце, концов, какой именно? Я же не сижу у вас за плечом), то следующий шаг делать: втыкать его пример в скетч-web-сервер...
Ну, поправка как "пусть вначале заработает хоть как-то", по быстрому - выглядить верно :)
Но, потом, нужно "переделать по уму".
А "по уму", get1wireDevices() изначально предназначалась не для "опроса показаний датчиков", а для "получения списка датчиков". А то что там вывелась какая-то температура - это просто "для теста", что датчик вообще работает и что-то послывает ардуине.
Само решение использовать дергать /getenv - imho неправильное.
IMHO опрос датчиков нужно либо добавлять в commandsStatus()
либо, делать отдельную команду-обработчик для нее.
Либо по аналогии с commandsStatus() и "регистрировать" ее в gCommandTable[]
Либо, по аналогии с get1wireDevices() и "регистрировать" ее через webserver.addCommand()
И... в этой комманде я бы не делал, как сейчас в get1wireDevices постоянный поиск датчиков "с нуля". Просто опрашивал-бы уже найденные, вот если ранее найденный "перестал отвечать", вот тогда можно выполнить поиск "заново".
Еще, как вариант. Где-нибудь в loop() постоянно опрашивать (ну с каким-то интервалом) температуру и складывать ее в какую-нибудь глобальную переменную. Вне зависимости от того "есть запрос или нет".
А в commandsStatus() просто выводить значение этой переменной. То есть разделить "опрос датчиков" и "обработка запроса".
Тогда и "примеры из библитеки датчиков" пойдут в скетч с "минимальными переделками". Просто вместо Serial.println, в какую-нибудь переменную сохранять полученное значение.
Если потом, у нас поменяется тип датчика. Скажем будет DHT11, то мы, опять-таки переделаем только "его опрос", а сами обработчики http запросов уже трогать не будем. Они как выводили "Значение переменно", так и будут продолжать выводить.
Вы правы, конечно нужно делать как Вы предлагаете.
В дальнейшем (с опытом) так наверное и будет.
Это времянное решение, хотя нет ничего постоянней, чем времянное решение.
Делаю это для теплицы, лето близится к концу. А вот в долгими зимними вечерами уже буду понимать, что, зачем и как мне нужно построить. Так что этот проект не "космический корабль" а всего лишь запчасти к нему.
Подскажите плз, я пока не понимаю алгоритм. Как в loop() опрашивать датчики с некой переодичностью.
А вот за этот пример отдельное спасибо. Его я раньше не видел и не искал, так как не было такой необходимости и такая мысль мне в голову не приходила. Мигал всегда только через delay().
А вот за этот пример отдельное спасибо. Его я раньше не видел и не искал, так как не было такой необходимости и такая мысль мне в голову не приходила. Мигал всегда только через delay().
Ну так вообще, нужно пойти в раздел "Программирование" (в шапке сайта). Просмотреть там ВСЕ. Хотя-бы "бегло". Что-бы хотя-бы знать какие "строительные блоки у нас существуют". Все функции, все примеры (особенно которые названы "базовыми и необходимыми...").
А потом, когда уже свой проект делаете, вспоминаете "где-то я видел подобное..." идете и читаете уже детаельно. Вникая.
То же самое с "прикрепленными темами". Что-бы когда понадобится, не ждать пока "кто-нибудь подскажет", а самому знать "где примерно искать".
Leshak, ну мы же знаем, на сколько временное постоянно, работает и ладно. Вот читаешь вас и понимаешь, на сколько скудны знания мои, и в какую сторону идти копать. Рад здоровой атмосфере на форуме.
Так что этот проект не "космический корабль" а всего лишь запчасти к нему... Припоминаю у нас так одна ракета завалилась ))
В целом, микроконтреллер должен выполнять все алгоритмы сам, без участия компьютера, а компьютер необходим лишь для визуального контроля и ручного управления. Собственно перекладывать функцию опроса датчиков на сам датчик, не особо практично. При условии, что в квартире будет 10-20 датчиков, и уже вшитых в стены, на сколько практично будет их перепрограммировать на новые адреса сервера? Или после изменения свойств в таблице баз данных, не проще переписать скрипт на сервере, чем каждый отдельный датчик. Нужна универсальность и масштабируемость, но если эти данные писать в железку, то ничего этого не будет.
Что-то я запутался в Ваших рассуждениях :)
Дуня сама посылает данные на сервер.
Поменялся адрес сервера? Как часто он у Вас меняется? И старый насовсем пропадает?
А если датчик выйдет из строя, что по моему гораздо реальнее чем смена сервера :)?
Изменение свойств в таблице баз данных???? Кхм... Вы напряму в БД пишите нативным драйвером?
Нафига? Если цель - положить показания датчика в базу? Зачем еще что-то отвечать, городить парсинг ответа на ардуине и т.п.? Послали данные - и все. Ну максимум проверили что http 200 вернулся (если нет - зажгли какую-то красную аварийную лампочку). И то... уже "по желанию".
Поднимать на Дуне клиента и сервер? Или как мы будем с телефона лампочкой мигать?
Холивар на тему как лучше и хуже, считаю пустым. Если JollyBiber считает что обратная связка лучше, то я с ним и соглашусь, но реализация при опросе датчиков сервером, мне больше по душе. Leshak, по контексту я догадался, и не более, что при запросе/обновлении страницы, данные должны обновляться. Но к сожалению этого не происходит. Я постоянно нажимаю F5 + сервер отправлет запрос через php скрипт, что равнозначно обновлению страницы, но данные не меняются. Хотя датчик нагреваю зажигалкой. И только после перезагрузки arduino данные обновляются. Не знаю почему так. Если кто-то может подсказать, скажите в чем дело. Код на всякий слуйчай еще рах прикреплю:
Заранее благодарен за помощь
JollyBiber, даже сейчас это отстраивается на виртуальном сервере. В планах переносить это на физический. На этом сервере имеем web-морду c указанием в настройках IP адреса "Arduino". Arduino получает IP адрес по DHCP. На роутере, или DHCP серваке пробиваем по мак адресу или номеру устройства IP адрес железки и имеем полный доступ к ней, например такой как здесь: http://www.ab-log.ru/smart-house/ethernet/megad-panel И я считаю это более чем удобно. Все-же холивар на эту тему, не уместен в данном вопросе. Человеку нужно найти решение именно в решении его задачи, а не рассуждать как это лучше. Если оно действительно лучше, то это придет только с опытом и пониманием всего и вся. А в задаче ТС уже найдено решение, и спасибо данному форуму за это.
sensors.requestTemperatures();
Не смог найти еще где-то кроме сетапа. Мож я чего проглядел?
ПыСЫ: я не говорил лучше, я говорил проще.
Да, собственно это есть только в SETUPe, сам больше не нашел.
Divest, да развеж я против? Удобнее - так пользуйтесь на здоровье. Я прописал IP статически и ничего не пробиваю :) На вкус и цвет все фломастеры разные.
Вот нашёл в опросе
float tempC = sensors.getTempC(Termometers);
Но у меня не поличилось вывести (в другом проекте) через
server.print(tempC);
если переменная float а не int.
Вот нашёл в опросе
float tempC = sensors.getTempC(Termometers);
Ну, вроде верно нашли :)
Осталось только опять применить принцип, не строить сразу космический корабль, вначале запчасти по одной проверить.
Вы, в режиме реального времени с датчика температуру научились получать? Без серверов и запросов. Обыкновенным serial.println() видеть как нагревание пальцами дает увеличение цифр в Serial Monitor-е?
Прежеде чем браться за отправку данных с ds1820 через шилды... может просто нужно корректно научится ее получать регулярно?
Какой библиотекой у вас происходит работа с датчиком? DallasTemperatureControll. А библиотека что имеет? Правильно. Примеры. Вот вначале нужно и убедится в их работе. Разобрать построчно "что деалает каждая строчка".
Ну а потом, будете смотреть, "в чем разница". Между содержимым loop() в примере и вашей get1wireDevices(... ) . Смотреть "чего же не хватает" (кстати выше - уже намекнули чего).
Я бы рекомендовал начать, как ни странно, с примера с именем "Simple". А все эти обнаружения отключения датчиков на ходу, работу с несколькими датчиками.... оставил бы на потом.
Кстати изначально-то getdev это команда получить список устройств. А не "получить температуру".
Заведите себе еще одну комманду. создайте, по аналогии функцию getTemp()
и добавте ее в спискок доступных комманд:
И уже в нее пихайте куски из библиотечного примера (после того как запустите сам пример).
Leshak, Interkom, спаисбо большое. Leshak, у меня получилось простым примером определять температуру с датчиков, и делать опрос нескольких датчиков, по библиотеке OneWire. И можно сказать что я в целом разобрался. Но некоторые вещи просто вылетают у меня из виду. И да, вы больше чем правы, мне нужно больше изучать основы, чем пытаться брать наскоком. Будем курить мануалы.
Leshak, у меня получилось простым примером определять температуру с датчиков, и делать опрос нескольких датчиков, по библиотеке OneWire.
Зачем OneWire? Можно конечно "чистым OneWire", но ведь есть DallasTemperatureControll. Которая и есть обертка над OneWire. Для упрощения. Тем более что эта библиотека - у вас уже подключена.
Ну, вот теперь берете тот пример (предварительно построчно его осознав) .... заворачиваете в функцию которая вызывается по http запроcу, заменяете Serial.println, на server.print.....
Кстати можно не заменять, а рядышком их...
Что-бы одновременно и в Serial-мониторе видеть, и в браузере... В сериал мониторе смотреть "вот пришел запрос", "вот опросили датчик", "вот получили такую температуру", "вот отправили ответ браузеру...".
Что-бы легче понять "что там вообще происходит.
Кстати, спрошу возможно дурацкий вопрос (к сожалению не всегда), а вы вообще знаете где примеры "идущие с библиотекой смотреть"? Или "что нашлось в гугле то и пробуем"?
Leshak, надеялся что у "спецов" в данной теме не совсем уж такое мнение обо сложится. Примеры идут вместе с библиотеками. Либо через файл-примеры. Либо через папку с библиотекой, Examples. Странно, но библиотека DallasTemperature у меня идет с примерами в ArduinoTemperatureControlLibrary, качал с гита. 1-wire отдельно. Но там уже есть примеры и мне собственно они понятны.
Leshak, надеялся что у "спецов" в данной теме не совсем уж такое мнение обо сложится.
Вот тоже делать нечего... мнения складывать :) Если вы думаете что один раз приходилось рассказывать про такой волшебный источник примеров :)
Странно, но библиотека DallasTemperature у меня идет с примерами в ArduinoTemperatureControlLibrary,
Ничерта не понял. Возможно это намек на какой-то "конфликт библиотек".
качал с гита. 1-wire отдельно. Но там уже есть примеры и мне собственно они понятны.
Ну 1-wire - это само собой. Она нужна в любом случае. Просто это "универсальная библиотека" которая как-бы для любых датчиков которые используют эту шину. И нее в примерах, ds1820 идет, конечно как пример работы с датчиком, но... в силу ее универсальности - использовать 1-wire в сыром виде - не слишком удобно.
DallasTemperatureControl это уже обертка над OneWire. Для облегчения работы конкретно с этим датчиком. Еще один слой абстракции (но внутри, она сама, естественно OneWire использует).
Ну и, в конечном итоге, я так и не понял... получилось у вас или нет? Если "пример запустился" (в конце, концов, какой именно? Я же не сижу у вас за плечом), то следующий шаг делать: втыкать его пример в скетч-web-сервер...
Вчера время абсолютно не было сидеть за компьютером. Сегодня постараюсь доделать его.
Добрый день. Полностью согласен с "Divest" #60.
Курение мануалов помогло (мне так показалось :-) ).
Я добавил всего одну строчку до цикла с выводом датчиков с показаниями.
Привожу только кусочек кода, так как пока не получается нормально вставлять коды.
Температура начала меняться. Пока только один датчик прицеплен к MEGE, скоро припаяю ещё несколько.
О результатах напишу.
Ну, поправка как "пусть вначале заработает хоть как-то", по быстрому - выглядить верно :)
Но, потом, нужно "переделать по уму".
А "по уму", get1wireDevices() изначально предназначалась не для "опроса показаний датчиков", а для "получения списка датчиков". А то что там вывелась какая-то температура - это просто "для теста", что датчик вообще работает и что-то послывает ардуине.
Само решение использовать дергать /getenv - imho неправильное.
IMHO опрос датчиков нужно либо добавлять в commandsStatus()
либо, делать отдельную команду-обработчик для нее.
Либо по аналогии с commandsStatus() и "регистрировать" ее в gCommandTable[]
Либо, по аналогии с get1wireDevices() и "регистрировать" ее через webserver.addCommand()
И... в этой комманде я бы не делал, как сейчас в get1wireDevices постоянный поиск датчиков "с нуля". Просто опрашивал-бы уже найденные, вот если ранее найденный "перестал отвечать", вот тогда можно выполнить поиск "заново".
Еще, как вариант. Где-нибудь в loop() постоянно опрашивать (ну с каким-то интервалом) температуру и складывать ее в какую-нибудь глобальную переменную. Вне зависимости от того "есть запрос или нет".
А в commandsStatus() просто выводить значение этой переменной. То есть разделить "опрос датчиков" и "обработка запроса".
Тогда и "примеры из библитеки датчиков" пойдут в скетч с "минимальными переделками". Просто вместо Serial.println, в какую-нибудь переменную сохранять полученное значение.
Если потом, у нас поменяется тип датчика. Скажем будет DHT11, то мы, опять-таки переделаем только "его опрос", а сами обработчики http запросов уже трогать не будем. Они как выводили "Значение переменно", так и будут продолжать выводить.
Вы правы, конечно нужно делать как Вы предлагаете.
В дальнейшем (с опытом) так наверное и будет.
Это времянное решение, хотя нет ничего постоянней, чем времянное решение.
Делаю это для теплицы, лето близится к концу. А вот в долгими зимними вечерами уже буду понимать, что, зачем и как мне нужно построить. Так что этот проект не "космический корабль" а всего лишь запчасти к нему.
Подскажите плз, я пока не понимаю алгоритм. Как в loop() опрашивать датчики с некой переодичностью.
Подскажите плз, я пока не понимаю алгоритм. Как в loop() опрашивать датчики с некой переодичностью.
"Как опрашивать" - смотрим примеры идущие с библиотекой DallasControll
"Как делать какое-то действите переодически" - смотрим Мигаем светодиодом без delay()
P.S. Вообщем любой проект должен начинаться с 100% осваивания кнопок и светодиодов, во всех мыслимых и не мыслимых комбинациях :)
"Как делать какое-то действите переодически" - смотрим Мигаем светодиодом без delay()
А вот за этот пример отдельное спасибо. Его я раньше не видел и не искал, так как не было такой необходимости и такая мысль мне в голову не приходила. Мигал всегда только через delay().
Пример интересный, буду изучать и анализировать.
А вот за этот пример отдельное спасибо. Его я раньше не видел и не искал, так как не было такой необходимости и такая мысль мне в голову не приходила. Мигал всегда только через delay().
Ну так вообще, нужно пойти в раздел "Программирование" (в шапке сайта). Просмотреть там ВСЕ. Хотя-бы "бегло". Что-бы хотя-бы знать какие "строительные блоки у нас существуют". Все функции, все примеры (особенно которые названы "базовыми и необходимыми...").
А потом, когда уже свой проект делаете, вспоминаете "где-то я видел подобное..." идете и читаете уже детаельно. Вникая.
То же самое с "прикрепленными темами". Что-бы когда понадобится, не ждать пока "кто-нибудь подскажет", а самому знать "где примерно искать".
Leshak, ну мы же знаем, на сколько временное постоянно, работает и ладно. Вот читаешь вас и понимаешь, на сколько скудны знания мои, и в какую сторону идти копать. Рад здоровой атмосфере на форуме.
Так что этот проект не "космический корабль" а всего лишь запчасти к нему... Припоминаю у нас так одна ракета завалилась ))
Полностью поддерживаю !!!
:-)
Будем стараться делать "хорошие запчасти". Жаль, но такое приходит только с опытом !!!