Передача температуры за окном на веб-сайт

Тема в разделе "Посоветуйте детальки", создана пользователем HighDigital, 16 июл 2013.

  1. HighDigital

    HighDigital Гик

    А где он будет это отображать? точнее как? я просто непрерывно пробовал посылать, он не выводит
     
  2. XCB

    XCB Гик

    К сожалению не силен в PHP, но попробуйте банально писать на хосте в файл, дата время - показания.
     
  3. HighDigital

    HighDigital Гик

    Ну вот, полностью разобрался с передачей команд, осталось только разобраться с приёмом.
    Немного лирики:
    Долго не мог понять, почему посылаю "1" из пхп, а он нифига не отвечает, пробовал ставить if(usb == 1) и if(usb == 49) - один фиг. Отследить не мог, что приходило, т.к СОМ порт при передаче занят, соответственно не прочитаю, пока занят... Тогда решил пойти тяжелой артиллерией - LCD дисплей. Сделал простой скетч, который отображает на ЛСД что приходит на СОМ. И вот аномалия! Отправляю "1", а приходит не "1", и не "49" (по ASCII), а приходит "177".
    Втф? Вот я по-эксперементировал, "Что отравил --> Что получил":
    Цифры "3, 5, 6, 9" - соответствуют таблице ASCII, но откуда у остальных такие номера? Для меня это осталось загадкой...
     
  4. HighDigital

    HighDigital Гик

    Тем не менее, сделал простой код, который при получении команды "ON-" в СОМ порт - включает светодиод и отображает на LCD "Led: ON", а "OFF-" соответственно выключает и отображает "Led: OFF".
    С обработкой команд заморачивался не долго, торопился, где-то возможны недочеты, возможно что то можно было сделать проще/правильнее. Но скетч рабочий.
    Код (C):
    /*
      Скетч для выполнения команд из нескольких символов.
      Команда обязательно должна заканчиваться "-", иначе она не будет распознана как команда, а как незаконченная команда.
      для профилактики, отправьте "-" в СОМ порт, это спровоцирует проверку команды и очистку массива.
     
      Принцип работы:
      Если что-то приходит в порт, включается цикл "Считывание".
      Сохраняем все в массив com[], пока не прийдет стоп-ключ "-" (ASCII = 45).
     
      Начинаем расшифровывать, что пришло.
      Проверяем простым способом - складываем весь массив в int sum;
      По сумме, проверяем, есть ли такая команда в нашей "базе данных":
     
      Если есть, отправляем положительный ответ, ставим переключатель stats=1(для активации основного кода), чистим наш массив, выходим из цикла. Выполняем основной код.
      Если такой команды нет, чистим массив, отправляем отрицательный ответ, обнуляем сумму проверки.
     
      Команды: "ON-" - включаем светодиод
               "OFF-" - выключаем светодиод
     
    */

    #include <LiquidCrystal.h>
    LiquidCrystal lcd(4, 5, 10, 11, 12, 13);

    int ledPin = 13; //Led

    //Принимающие
    int usb = 0; //in Serial
    int com[16] = {0}; //massive (В него сохраняем команды)
    //
    int stats=0; //Если "=1" - переходим к выполнению основного скетча
    int sum=0; //Сумма команды
    int buf=0; //переключатель "ячеек" массива


    void setup() {
      pinMode(ledPin, OUTPUT);
      Serial.begin(9600);
      lcd.begin(16, 2);
      delay(200);
    }
    void loop() {
      //Ожидаем символов с СОМ порта.
      while (Serial.available() > 0)
      {
        //Записываем все в массив
        buf++; //переключатель "ячеек" массива
        usb = Serial.read(); //Запоминаем пришедший символ.
        com[buf] = usb; //Записываем его в ячейку
       
        if(usb == 45) //Если пришел стоп-ключ "-", считываем массив для распознания команды
        {
          //Нужно проверить сумму команды, если пришла неправильная команда, стираем буфер, заного считываем.
          for(int h=0; h<16; h++) sum = com[h] + sum; //Складываем все символы команды в int, по сумме понимаем - правильная команда или нет.
         
          //Наша база данных
          if(sum == 330) //команда "ON-"
          {
            //Serial.println("Accept command");
            stats=1; //переходим к основному скетчу
            buf=0; //обнуляем переключатель
            for(int y=0; y<16; y++) com[y]=0;
            break; //выходим из цикла
          }
          else if(sum == 648)//команда "OFF-"
          {
            //Serial.println("Accept command");
            stats=1; //переходим к основному скетчу
            buf=0; //обнуляем переключатель
            for(int y=0; y<16; y++) com[y]=0;
            break; //выходим из цикла
          }
          else
          {
            //Очистка массива
            for(int y=0; y<16; y++) com[y]=0;
            //Serial.println("Fail command");
            sum=0; //обнуляем проверку
          }
        }
       
      }
     
      //Скетч (основной код)
      if(stats == 1)
      {
        if(sum == 330) //ON Led
        {
          digitalWrite(ledPin, HIGH);
          lcd.clear();
          lcd.print("Led: ON");
        }
        else if(sum == 648) //OFF Led
        {
          digitalWrite(ledPin, LOW);
          lcd.clear();
          lcd.print("Led: OFF");
        }
        sum=0; //Обнуляем сумму
       
       
        stats=0; //Возвращаемся в режим считывания
      }
    }
     
    sadmin нравится это.
  5. HighDigital

    HighDigital Гик

    А вот что на стороне сервера, на странице две кнопки "ON" и "OFF"
    А также строка для ручного ввода команд.
    PHP:
    <?php
    include "scripts/php/php_serial.class.php";
    $serial = new phpSerial;
    $serial->deviceSet("COM3"); //это у Windows, для линукса /dev/ttyS0
    $serial->confBaudRate(9600); //Baud rate
    $serial->confParity("none"); //Parity (this is the "N" in "8-N-1")
    $serial->confCharacterLength(8); //Character length (this is the "8" in "8-N-1")
    $serial->confStopBits(1); //Stop bits (this is the "1" in "8-N-1")
    $serial->confFlowControl("none");
    if (isset($_GET['str'])){
    $serial->deviceOpen();
    $serial->sendMessage($_GET['str']);
    $serial->deviceClose();
    }
    if (isset($_GET['on'])){
    $serial->deviceOpen();
    $serial->sendMessage("ON-");
    $serial->deviceClose();
    }
    if (isset($_GET['off'])){
    $serial->deviceOpen();
    $serial->sendMessage("OFF-");
    $serial->deviceClose();
    }
    ?>
    <div align="center">
    <form action="<?=$_SERVER['PHP_SELF']?>">
    <p><input name="on" type="submit" value="  ON  "> <input name="off" type="submit" value="  OFF  "></p>
    </form>
    <form action="<?=$_SERVER['PHP_SELF']?>">
    <p>COM: <input name="str" autofocus required list="var1" size="13" maxlength="5" placeholder="Enter command" type="text" autocomplete="off">
    <datalist id="var1">
    <option value="ON-">
    <option value="OFF-">
    </datalist>
    <input value=" Send " type="submit"></p>
    </form>
    </div>
     
    sadmin нравится это.
  6. HighDigital

    HighDigital Гик

    Надеюсь я кому-нибудь помог.
    Осталось разобраться, как вывести на страницу что пришло из СОМ порта, в скором времени узнаю...
     
    sadmin нравится это.
  7. HighDigital

    HighDigital Гик

    Разобрался с приходом "левых" цифр, не соответствующих ASCII таблице:
    Решение очень простое, в коде поменял такое:
    Код (C):
    //Записываем все в массив
        buf++; //переключатель "ячеек" массива
        usb = Serial.read(); //Запоминаем пришедший символ.
        com[buf] = usb & 0x7F; //Записываем его в ячейку
    Теперь все правильно приходит:
     
  8. Nickstalker

    Nickstalker Нерд

    Попробуйте написать приложение ASP.NET, данная платформа имеет очень интересный класс System.IO.Ports.SerialPort, который позволяет легко взаимодействовать с COM портом Arduino.
    ЗАГОТОВКА (C# 3.5 ASP.NET, стандартное содержимое пропускается, на отображаемой странице (обычно Default.aspx) объявлен таймер Tim, лэйбл Lab):
    ...
    using System.IO.Ports;
    namespace Imyarek
    {
    class Imya_Rek
    {
    SerialPort sp;
    public void PageLoad(object sender, event Args e)\\или как-то так, метод вызываемый при загрузке страницы
    {
    sp=new SerialPort("nazvanie", skorost_v_bodax);
    try
    {
    sp.Open();
    }

    catch(Exception)
    {
    Response.Write("Ошибка подлючения!!!<br>");
    }
    tim.Enabled=true;
    }
    public void Tim_tick(object sender, event Args e)\\метод вызываемый при тике таймера
    {
    if(sp.IsOpen==true)
    {
    try
    {
    string temp=sp.ReadLine();
    int tempC=Convert.ToInt32(temp);
    int pempF=tempC*100/37;
    Response.Write("C: "+Convert.ToString(tempC)+" ;F: "+Convert.ToString(tempF)+"<br>";
    }
    catch(Exception)
    {
    }
    }
    }
    }
    }
    Код не совершенен и с первого раза не заработает ввиду его не полности (надо дополнить автоматически генерируемым средой обязательным кодом и страницей привязки), но его достаточно, чтобы понять простоту работы с данным классом.
    Желаю удачи!
     
  9. HighDigital

    HighDigital Гик

    Хорошо - приму во внимание.
     
  10. Megakoteyka

    Megakoteyka Оракул Модератор

    Переведите эти числа в hex и увидите, что в старшем разряде сидит бит дополнения до четности.
    Такое впечатление, что порт настроен на формат "7 бит данных, дополнение до четности". Настройте порт как "8 бит, без контроля четности" и тогда все должно приходить правильно.
     
  11. NR55RU

    NR55RU Гик

    Я бы поступил чуть иначе.
    Проект имеет высокую сцепку, то есть чтобы он работал надо чтобы Дуня была подключена к серверу и при этом использовать ПХП для работы с ком портом, нет гибкости.
    Я бы поступил следующим образом.
    С дуней я бы работал на Си например, получал бы данные с дуни к примеру раз в какой то промежуток времени, эти данные на выбор:
    а) складывал бы в локальный файл из которого ПХП потом бы читала
    б) по сокету кидал любому серваку в мире, который готов эти данные принять обычным POST или GET методом (пофигу где стоит сервер)
    в) организовал бы порт приема запросов, при поступлении запроса программа возвращает значения.

    Все 3 варианта предоставляют на мой взгляд:
    а) отсутствия тесной связи веб-серва + дуни.
    б) уводим ПХП от работы которая ну по сути не совсем для нее, чтения с ком портов, передаем эту работу более подходящему языку плюс который умет жить в памяти.
    в) Имеем очень полезную фитчу, например если программа висит в памяти (ПХП это не умеет, если только крон на линуксе мучать с регулярными запусками) и получает данные от датичка, при получении некоего сигнального значения, программа по инету может оповестить любой ПХП на любом сервер о факте достижения этого значения, проще говоря мы можем не просто получать по запросу мы можем сделать прогу активной которая сама оповестит нас или что то сделает когда что то случится.
    г) Что очень важно, мы не задерживаем страницу загрузки сайта, пока ждем считывание данных с дуни если схема реализована по принципу складывания данных в фаийл или же когда программа сама передает раз в какое то время данные с датчика а ПХП там на сервере куда то их себе складывает чтобы потом быстро показать.

    Все клева, кроме одного, для всего этого надо будет знать такой язык типа Си, но на мой взгляд если вы уж занялись такими вещами железными то один фиг придется :)
    Да и статей по работе с ком портом в том же Си в разы больше чем в ПХП.

    Ну собственно в общих чертах примерно так. Все написано на вскидку, но возможно почерпнете идею какую.

    P.s. Тут бы подошла идеология шаблона "слушатель". Оповещать сервер лишь тогда когда что то изменяется, к примеру кидать на сервер из программы новое значение температуры лишь когда она изменилась, это избавляет от постоянных передач одинаковых значений если ничего не происходит, снижение нагрузки, меньше ненужной работы. Ээээ соррри, просто не могу избавится от параноидальной привычки искать наиболее оптимальное решение :)
     
  12. NR55RU

    NR55RU Гик

    Если Вас не затруднит, вы могли бы пояснить смысл вот этого 1 бита честности.
    Я при изучении структуры DCB сталкивался с этой настройкой, но в описании не было уделено этому внимания. При настройках на 8 бит, все работало и я на тот момент не стал разбираться детально.
    Рискну предположить что данный бит добавляется тогда когда одна железка оперирующая 7 битными данными, хочет передать другой железки которая оперирует 8 битными данными, свои данные.
    Таким образом получается что 7 битная железка кидает первым старший бит-заглушку (наверное это ноль) а за ним идет уже 7 бит данных, а 8 битная железка стандартно принимает свои 8 бит данных и размещает их в ячейках.
    Таким образом если мы с 7 битной железки попытаемся отправить 8 бит данных в виде скажем 11111111 (8 единиц) то железка сделает финт, отправив в первой партии к примеру 01111111 а во второй 00000001
    И вместо одного байта данных на 8 битной железке мы получим 2 байта.
    Я хотя бы примерно прав ?:)
    И для чего вообще введены такие режимы отличные от 8 битов, для совместимости с каким либо устройствами ?
     
  13. Megakoteyka

    Megakoteyka Оракул Модератор

    Бит дополнения до четности используется для контроля передачи. В передаваемом байте подсчитываются все единички. Если их число четное - бит встает в 0, иначе в 1. На приеме производится проверка - если бит не совпал - байт отбрасывается. Обычно этим не пользуются, ставят режим 8n1 (8 бит данных, 1 стоповый бит, без контроля четности).
    Бит четности
     
  14. NR55RU

    NR55RU Гик

    Ах тыж блин, мои рассуждения пошли совсем не в ту степь, это оказывается для проверки правильности передачи данных, если к примеру получен бит четности 0 а единиц пришло лишь 5 то железка поймет что произошла ошибка так как единиц должно быть четное число и сделает соответствующие действия для данной ситуации.
    Спасибо большое.
    Думаю мне пора детально "покурить" ченить о серийной коммуникации на уровне сигналов дабы получше понимать сей спект.
     
  15. Dencraft23

    Dencraft23 Нуб

    Где можно стандартные руки заказать?
     
  16. Megakoteyka

    Megakoteyka Оракул Модератор

    Вы о чем? Темой не ошиблись? :)
     
  17. Unixon

    Unixon Оракул Модератор

    Неужели что то настолько не получается, что понадобились стандартные прямые руки с креплением на плечевой сустав? :eek:


    Манипулятор-рука для робота? :rolleyes:
     
  18. sadmin

    sadmin Нуб

    HighDigital, спасибо! Ваши эксперименты весьма помогли.
     
  19. n007

    n007 Нуб

    dht11 для «температуры за окном» не подходит.
    Диапазон температур у него 0–50 °С