2013-06-25 3 views
1

Я пытаюсь подключить Arduino Uno к датчику температуры с использованием I2C. Сначала Arduino может отправлять поток данных, но он останавливается на несколько минут позже ...Arduino I2C - поток данных неожиданно остановился

Если я перезапущу плату, Arduino может отправить поток данных, но снова он остановится через несколько минут. Интересно, ошибочно ли мой код. Пожалуйста, помогите мне.

/* 
Program akses DT-SENSE Temp SENSOR - Arduino 
Vizard Vision @ 2013 
*/ 
#include <Wire.h> 
void setup() { 
    Wire.begin();    
    Serial.begin(38400);  
} 
int buffer = 0; 
int count = 0; 
void loop() { 
    if(count >= 6000) { 
    count = 0; 
    } 
    Wire.beginTransmission(112); // transmit to device #112 (0x70) 
    // the address specified in the datasheet is 224 (0xE0) --> 1110 0000 = E0H 
    // but i2c adressing uses the high 7 bits so it's 112 --> 0111 0000 = 70H 
    Wire.send(0x00); 
    // command sensor to measure 16 Byte of Temperature Data 
    Wire.endTransmission();  
    delay(100);    

    Wire.requestFrom(112, 2); 
    // request 2 bytes from slave device #112 
    if(2 <= Wire.available()) { 
    // if two bytes were received 
    buffer = Wire.receive(); 
    // receive high byte (overwrites previous reading) 
    buffer = buffer << 8; 
    // shift high byte to be high 8 bits 
    buffer |= Wire.receive(); 
    // receive low byte as lower 8 bits 
    buffer = (buffer - 400)/10; 
    // Conversion data to Temperature (from datasheet) 
    Serial.print(count); 
    Serial.print(" Suhu = "); 
    Serial.print(buffer); 
    Serial.write(176); 
    // Unicode value of Degree Symbol 
    Serial.println("Celsius"); 
    count ++; 
    Serial.flush(); 
    } 
    delay(40); 
} 
+0

Это выглядит очень чисто. Вы можете установить задержку между вызовами Wire.requestFrom и Wire.available(). Странно, что буфер и подсчет являются глобальными. Но если бы я должен был догадаться, я бы сказал, что ваш бод 38400 - это быстрый способ для вашего кабеля. Просто догадка. –

ответ

1

Там может быть проблема здесь:

if(2 <= Wire.available()) // if two bytes were received 
    { 
    buffer = Wire.receive(); // receive high byte (overwrites previous reading) 
    buffer = buffer << 8; // shift high byte to be high 8 bits 
    buffer |= Wire.receive(); // receive low byte as lower 8 bits 

Он попадет в блок, если есть 1 или 2 байта доступны. Если есть 2 байта, он пройдет как Wire.receive(), так и ваша buffer переменная будет настроена правильно, и вы счастливы. Если есть только 1 байт, он пройдет первый Wire.receive(), а на втором у вас будет непредвиденное поведение (i.e. документация не сообщает, что он делает, когда это произойдет). Поэтому я ожидаю, что он будет блокироваться до тех пор, пока не появится байт, но поскольку он никогда не наступит, он блокирует бесконечно.

Тогда вы бы задались вопросом: «Почему это когда-либо возвращало бы один байт?». А может быть много причин:

  • техническое описание может лежать и на очень специфических обстоятельствах ваш i2c раб может возвращать один байт,
  • ваше соединение засланный в одной точке, а ведомый записывает оба байта в неверная скорость, заставляющая вашу либу считать, что это всего один байт,
  • есть ложный контакт в вашей строке i2c и при странных обстоятельствах (температура, давление, вибрация, шторм в Никарагуа), и только один из двух байтов проходит через подключение ...

Поэтому вы должны сделать следующее:

if(Wire.available() == 2) // if two bytes were received 
    { 
    buffer = Wire.receive(); // receive high byte (overwrites previous reading) 
    buffer = buffer << 8; // shift high byte to be high 8 bits 
    buffer |= Wire.receive(); // receive low byte as lower 8 bits 

, который поможет вам избежать неожиданного поведения!