Теплица управляемая по Bluetooth

vertraut
Offline
Зарегистрирован: 07.01.2016

Всем привет! Делаю теплицу с bluetooth управлением. Необходимо задавать настройки с телефона, а также на телефоне видеть показатели с датчиков теплицы.

Например, я хочу задать температуру, которая должа поддерживаться в теплице. Как сделать так, чтобы в телефоне можно было ввести значение, а оно установилось в ардуино? При этом, чтобы на телефоне отображалась текущая температура в теплице, включен обогреватель или выключен, а также видеть какая температура задана.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vertraut пишет:

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

Ну, как: сесть, почесать репу и сделать.

У Вас есть конкретный вопрос, что-то не получается? Или Вы хотите. чтобы кто-то за Вас от начала до конца сделал? Если второе, то Вам в другой раздел.

vertraut
Offline
Зарегистрирован: 07.01.2016

ЕвгенийП пишет:

Ну, как: сесть, почесать репу и сделать.

У Вас есть конкретный вопрос, что-то не получается? Или Вы хотите. чтобы кто-то за Вас от начала до конца сделал? Если второе, то Вам в другой раздел.

Как при помощи блютуз каманды определенной переменной присвоить значение? Все проекты которые я находил с управлением по блютуз ограничиваюся отправкой 0 для выключения, а 1- включение. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vertraut пишет:

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

И что?

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

vertraut пишет:

Как при помощи блютуз каманды определенной переменной присвоить значение? 

Это не конкретный вопрос. Покажите код и скажите, что не получается. На такой вопрос как у Вас и ответ соответсвующий: получите значение и не включайте-выключайте, как в Ваших примерах, а присвавайте чему нужно. Что именно у Вас не получается?

 
vertraut
Offline
Зарегистрирован: 07.01.2016

ЕвгенийП пишет:

Это не конкретный вопрос. Покажите код и скажите, что не получается. На такой вопрос как у Вас и ответ соответсвующий: получите значение и не включайте-выключайте, как в Ваших примерах, а присвавайте чему нужно. Что именно у Вас не получается?

 

Насколько я понял, по блютуз можно передавать информацию только побитово. Допустим, я хочу отредактировать предел температуры первого датчика, отправляю команду temp1_25, ардуина берет каждый символ и пока не нашла символ "_" все записывает в переменную name, после чего остаток в буфере записывает в переменную value. Далее мы определяем по переменной name, какой параметр мы редактируем и присваеваем этому параметру value.

Написал простенький код, задача которого считать биты и отправить из словом на телефон. Но почему-то приходит посимвольно... Т.е. отправляю ему hello, в ответ String: h String: e String: l String: l String: o. Как определить что данных в буфере больше нет?

 

char incomingByte;  // входящие данные
String s;

void setup() {
  Serial.begin(9600); // инициализация порта
}

void loop()
{
  
 if (Serial.available()>0) {    //если есть что читать
  
   while (Serial.available()>0){//читаем пока есть данные
   char c = Serial.read();     //читаем символ
    s += c;                     //добавляем к строке
   }
      Serial.print("String: "); //выводим строку
      Serial.println(s);
      s="";
  
    }
 }

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

vertraut пишет:

Написал простенький код, задача которого считать биты и отправить из словом на телефон. Но почему-то приходит посимвольно... Т.е. отправляю ему hello, в ответ String: h String: e String: l String: l String: o. Как определить что данных в буфере больше нет? 

char incomingByte;  // входящие данные
String s;

void setup() {
  Serial.begin(9600); // инициализация порта
}

void loop()
{
  
 if (Serial.available()>0) {    //если есть что читать
  
   while (Serial.available()>0){//читаем пока есть данные
   char c = Serial.read();     //читаем символ
    s += c;                     //добавляем к строке
   }
      Serial.print("String: "); //выводим строку
      Serial.println(s);
      s="";
  
    }
 }

Ну, это нормально. Пока там Serial передаёт второй символ, Вы уже успеваете считать первый и получить нулевой Serial.available().

Можно, конечно, увеличить скорость Serial (она у Вас больно маленькая), но в общем случае это не поможет. Если хотите считывать строку целиком, придумывайте разделитель (терминальный символ - например, проблел или запятая) и передавайте его в конце. Тогда будете читать пока не получите разделитель - это сработает.

Если читать нужно, например, числа, так лучше воспользоваться специальными методами Serial'а -  parseInt, parseFloat. А для строк, если Вы придумаете терминальный сивол, тоже лучше не читать побайтово, а использовать специальный метод, например readStringUntil() - он сам дочитает до терминального символа и вернёт считанную строку.

vertraut
Offline
Зарегистрирован: 07.01.2016

ЕвгенийП пишет:

Ну, это нормально. Пока там Serial передаёт второй символ, Вы уже успеваете считать первый и получить нулевой Serial.available().

Можно, конечно, увеличить скорость Serial (она у Вас больно маленькая), но в общем случае это не поможет. Если хотите считывать строку целиком, придумывайте разделитель (терминальный символ - например, проблел или запятая) и передавайте его в конце. Тогда будете читать пока не получите разделитель - это сработает.

Если читать нужно, например, числа, так лучше воспользоваться специальными методами Serial'а -  parseInt, parseFloat. А для строк, если Вы придумаете терминальный сивол, тоже лучше не читать побайтово, а использовать специальный метод, например readStringUntil() - он сам дочитает до терминального символа и вернёт считанную строку.

Большое спасибо за помощь! Сейчас разберусь, надеюсь все получится!

vertraut
Offline
Зарегистрирован: 07.01.2016

Все работает замечательно, есть только небольшая задержка около секунды пока придет ответ. Сейчас можно отправить несколько команд разделенных "|" а в ответ каждая команда придет отдельно) Большое спасибо. Буду дальше разбираться!

void loop()
{
  
 if (Serial.available()) {    //если есть что читать
 s = Serial.readStringUntil('|');
 }
if (s.length()>0){
 Serial.println(s);
 s="";
}

 }

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, вот, и отлично. Только я бы ещё проверял, она действительно ввела строку или по таймауту вылетела. Там если юзер долго не вводит - таймаут есть. Его, кстати, изменять можно.

vertraut
Offline
Зарегистрирован: 07.01.2016

ЕвгенийП пишет:

Ну, вот, и отлично. Только я бы ещё проверял, она действительно ввела строку или по таймауту вылетела. Там если юзер долго не вводит - таймаут есть. Его, кстати, изменять можно.

Не совсем понял... или совсем не понял) Кто она? Куда ввела? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, readStringUntil('|') может не дождаться полной строки (если юзер заснул) и вылететь по таймауту. В этом случае она вернёт то, что успела ввести. Т.е. я бы подумал как это проверять.

По умолчанию таймаут, кажется, 1000мс. Можно установить свой функцией Serial.setTimeout(<время в мс>)

 

vertraut
Offline
Зарегистрирован: 07.01.2016

ЕвгенийП пишет:

Ну, readStringUntil('|') может не дождаться полной строки (если юзер заснул) и вылететь по таймауту. В этом случае она вернёт то, что успела ввести. Т.е. я бы подумал как это проверять.

По умолчанию таймаут, кажется, 1000мс. Можно установить свой функцией Serial.setTimeout(<время в мс>)

 

А, понял. А как определить уснул юзер или нет? Если это возможно, то нужно проверять состояние юзера, если уснул, то снова начать читать буфер в ноую переменную и объединитиь с предыдущей. Как я понял)

mozgolomys
Offline
Зарегистрирован: 08.01.2016

Извините, что вперся к вам, но в соседней ветке по сути похожий вопрос http://arduino.ru/forum/programmirovanie/webserver-na-arduino-2560-i-ethernet-kontrollere-w5100  не могли бы подсказать?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

К сожалению, сама readStringUntil никак не сообщает о таймауте. Она просто возвращает то, что успела прочитать.

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

Можно и по-другому: придумать терминальный символ не из одного символа, а из двух (это уже будет "терминальная последовательность"). Например: "~|". А readStringUntil  передавать только последний симвод '|'. Тогда, прочитав строку, Вы всегда можете точно узнать до конца она дочиталась или нет, т.к. если до конца, то она будет всегда оканчиваться на '~'.

Можно придумать кщё 100500 вариантов, но тут лучше понимать задачу и от неё исходить - Вам и карты в руки.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Кстати, есть более радикальный способ. Можно переопределить Serial, заменив в нём readStringUntil на собственную версию, которая будет возвращать сигнал о том. что был таймаут.

Оригинальная readStringUntil вот такая:

String Stream::readStringUntil(char terminator)
{
  String ret;
  int c = timedRead();
  while (c >= 0 && c != terminator)
  {
    ret += (char)c;
    c = timedRead();
  }
  return ret;
}

Как видите, она понимает, что произошёл таймаут, но не говорит об этом :)

Можно просто перегрузить её своей функцией. Если это критично и действительно надо - я бы так и сделал.

vertraut
Offline
Зарегистрирован: 07.01.2016

Ясно, спасибо!