Прошу помощи в реализации проекта.

Mezentsev
Offline
Зарегистрирован: 21.02.2014

Добрый день форумчане. Прошу помочь с реализацией проекта.

Итак. Есть Arduino Mega 2560, Arduino Uno, Ethernet Shield,Troyka Shield и датчик температуры DHT-11.

Идея заключается в следующем:

1) Arduino Mega 2560 и Arduino Uno соединить по I2C:

 

Скетчи для Master и Slave:

Для Master (Arduino Mega 2560):

#include <Wire.h>  //подключаем библиотеку
#define ADDR  2  //адрес нужного нам Slave 
 
void setup() 
{
  Wire.begin(); //включить i2c
}
 
void loop()// Главный цикл
{
  Wire.beginTransmission(ADDR); //начало передачи, с адресом нужного нам Slave
  Wire.write(111); //отправляем данные для выбраного Slave
  Wire.endTransmission();  //конец передачи
  delay(1000); //пауза
} 

Для Slave (Arduino Uno):

#include <Wire.h>
#define ADDR 2 //адрес устройства
 
void setup() 
{
Serial.begin(9600);//скорость обмена с компом
Wire.begin(ADDR); //определим как ведомый с указанным адресом
Wire.onReceive(receive_handler); //ждем данных от мастера, функция возвращает int число байт данных 
}
 
void loop() {}
 
void receive_handler(int numbytes) 
{
 for (int i=0;i<numbytes;i++) //читаем весь пакет 
  {
    Serial.print(Wire.read()); // принимаем значение и передаем компьютеру
  }
  Serial.println(' '); //перенос строки
}  

2) На Arduino Uno с Troyka Shield подключим датчик DHT-11:

Скетч:

#include <dht.h>



int ledPin = 13;
// Создаем сенсор
DHT sensor = DHT();
 
void setup()
{

    Serial.begin(9600);
 
    // Подключаем сенсор к 0 аналоговому порту
    sensor.attach(A0);

    // Ждем готовность сенсора
    delay(1000);
}
 
void loop()
{
    // Проводим измерения
    sensor.update();
 
    switch (sensor.getLastError())
    {
        case DHT_ERROR_OK:
            char msg[128];
            // Если ошибок нет, то собираем данные
            sprintf(msg, "Vlaznost = %d%% Temp = %dC", 
                    sensor.getHumidityInt(), sensor.getTemperatureInt());
            Serial.println(msg);
            break;
        case DHT_ERROR_START_FAILED_1:
            Serial.println("Error: start failed (stage 1)");
            break;
        case DHT_ERROR_START_FAILED_2:
            Serial.println("Error: start failed (stage 2)");
            break;
    }
 
    delay(1000);
}

3) На Arduino Mega 2560 и Ethernet Shield запускаю сервер для своих нужд:


#include <SPI.h>
#include <Ethernet.h>
 
// MAC адрес нашего  Ethernet шилда
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 244); // IP по которому мы будем обращаться к этой странице
EthernetServer server(80);  // порт 80
 
void setup()
{
    Ethernet.begin(mac, ip);  // запускаем Ethernet шилд
    server.begin();           // запуск web сервера
}
 
void loop()
{
    EthernetClient client = server.available();  // опрашиваем канал в поисках клиента
 
    if (client) {  // если клиент найден
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // если клиент доступен для чтения
                char c = client.read(); // читаем 1 бит полученный от клиента
                // <span style="font-size: 9pt; font-family: Consolas;">последняя строка запроса является пустой и заканчивается  </span>  \n
                // реагировать на клиента только после полного прочтения 
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    // send web page
                    client.println("<!DOCTYPE html>");
                    client.println("<html>");
                    client.println("<head>");
                    client.println("<title>Arduino Web Page</title>");
                    client.println("</head>");
                    client.println("<body>");
                    client.println("<h1>Привет от  Arduino!</h1>");
                    client.println("<p>Эта страница с WEB сервера Arduino </p>");
                    client.println("</body>");
                    client.println("</html>");
                    break;
                }
                //каждая строка полученная от клиента заканчивается  \r\n
                if (c == '\n') {
                    // последний символ принятого запроса
                    // начало новой строки для чтения
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // получение текстового символа от клиента
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // даем время для браузера получить данные
        client.stop(); // закрываем соединение
    } 
}

Вопрос: Как организовать передачу показаний с датчика температуры по шине I2C на сервер?

P.S. Ногами не бейте, первый раз собираю проект на ардуино. Заранее благодарен.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Зачем это ? Цель какую преследуете ?

Mezentsev
Offline
Зарегистрирован: 21.02.2014

Задача от преподавателя. Получение информации с датчика температуры на сервер второй платы Arduino

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

В общем не понятно. Датчик подключен к какому контролеру ?  Смысл в чем ? Объединть два контролера по i2c ?

Mezentsev
Offline
Зарегистрирован: 21.02.2014

Вы правы. Нужно подключить обе платы по I2C. Arduino Mega 2560 будет являться мастером.(на нем же и сервер),а на Arduino Uno подключен датчик температуры.(Uno - слейв) Показания датчика передать с Uno на Mega, и уже на Mega отправить их на сервер 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

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

Mezentsev
Offline
Зарегистрирован: 21.02.2014

т.е. SPI?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Нет, uart. Serial.print, Serial.read.

Mezentsev
Offline
Зарегистрирован: 21.02.2014

а примерчиком не поделитесь?

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Нет компа под рукой, пишу с планшета. Контролеры нужно соединить двумя проводами tx -> rx, rx-> tx. Uno у вас каждую секунду выдает сообщение "Vlaznost...." принимайте это сообщение на меге и встраивайте его в html страничку. Поищите тут на форуме "как собрать стринг с ком порта".

Mezentsev
Offline
Зарегистрирован: 21.02.2014

Спасибо за совет,будем пробовать через serial.

Mezentsev
Offline
Зарегистрирован: 21.02.2014
 Serial.println(msg);

это с Uno,а на Mega:


void setup() {
  Serial.begin(9600)
}
void loop() {

  while(Serial.read() > 0) {

    String ttydata = Serial.readString(); // ttyData - информация с серийного порта

  }

}

правильно понял?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Да, только вот не уверен, что readstring библиотечная функция. Помоему ее нужно написать.

Mezentsev
Offline
Зарегистрирован: 21.02.2014

вот примерчик нашел

int incomingByte = 0;   // переменная для хранения полученного байта
 
void setup() {
    Serial.begin(9600); // устанавливаем последовательное соединение
}
 
 
void loop() {
    if (Serial.available() > 0) {  //если есть доступные данные
        // считываем байт
        incomingByte = Serial.read();
 
        // отсылаем то, что получили
        Serial.print("I received: ");
        Serial.println(incomingByte, DEC);
    }
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Нет это не правильно. Правильно так http://arduino.ru/forum/programmirovanie/kak-sobrat-string-ot-com-porta#comment-9805 . Только Строки 5,6,7 нужно выбросить, вместо них вставить break;. А принятое сообщение будет в inString. 7 строку поставьте перед первой. Получится кусок кода принимающий сообщение, которое нужно воткнуть в веб страничку.

Garry
Garry аватар
Offline
Зарегистрирован: 07.04.2012

Старый мой тест для Меги (основа взята с arduino.cc):

// Тестируем Iteaduino Mega 2560 на совместимость с классом SerialX
// Тестируем void serialEvent2(). Работает!!!
// Замкнул перемычкой пины RX2 и TX2. Работает!!!
// !!! ACHTUNG !!! Есть небольшая задержка, первые несколько байт данных не передаются!
//                 После включения SerialMonitor следует подождать несколько секунд.
// !!! ACHTUNG !!! Работает даже без delay(50);


String inputString = "";         // строка для накопления данных с UART2
boolean stringComplete = false;  // флаг, строка пришла полностью, окончание строки по символу '\n'


void setup() {

  // резервируем место под строку
  inputString.reserve(200);
  
  Serial.begin(9600);
  
  Serial2.begin(9600);

}


void loop() {
  
  static int inByte;
  
  // UART0 --> UART2 (передаем посимвольно)
  if (Serial.available()) {
    
    inByte = Serial.read();
    Serial2.write(inByte);
    
  }
  
  //delay(50);
  
  // UART2 --> UART0 (передаем строкой)
  // выводим на монитор накопленную строку
  if (stringComplete) {
    
    Serial.print(inputString);
    
    // сбрасываем переменные для нового накопления строки
    inputString = "";
    stringComplete = false;
    
  }
  
  //delay(50);
  
}


void serialEvent2() {
  
  static char inChar;
  
  while (Serial2.available()) {
    
    inChar = (char)Serial2.read(); 
    
    // накапливаем строку из символов
    inputString += inChar;
    
    // получили окончание строки, можно обработать ее в главном цикле
    if (inChar == '\n') {
      
      stringComplete = true;
      
    }
    
  }
  
}

В примере используются оба варианта получения данных: посимвольный и строковый (класс String), кроме того, в варианте со String используется стандартный void serialEvent2() для отделения кода приема данных с UART2 от главного цикла программы. Для избежания багов при переполнении строки можно в serialEvent добавить код для проверки длины накопленной строки с максимальной зарезервированной под ее длиной.