Одновременная работа нескольких DS18B20 и DHT11
- Войдите на сайт для отправки комментариев
Вс, 11/01/2015 - 14:13
Здравствуйте.
Странная проблема с обнаружением устройств на шине 1-wire при подключенном DHT11.
1-wire определена на 4 пин. Через резистор 4.7кОм переллельно подключено 5 датчиков DS18B20.
DHT11 тоже через 4.7кОм на 5 пин.
+5 В, GND беру с пина 5V, GND на arduino.
Отдельно все работает. Но при подключении DHT11 перестают корректно обнаруживаться датчики DS18B20.
#include <OneWire.h>
#include "DHT.h"
#include <LCD5110_Graph.h>
#include <SoftwareSerial.h>
#define DHTPIN 7
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
OneWire ds (4); // все OneWire устройства на pin 4
//int led_pin=13; // определили pin 13 для светодиода
byte done[8];
LCD5110 myGLCD(9,10,11,12,13);
extern uint8_t SmallFont[];
#define rxPin 2
#define txPin 3
SoftwareSerial mySerial(rxPin, txPin);
void setup()
{
dht.begin();
myGLCD.InitLCD();
myGLCD.setFont(SmallFont);
mySerial.begin(19200); // the GPRS baud rate
Serial.begin(19200); // the Serial port baud rate
Serial.println("ElecFreaks EFComs Start");
myGLCD.clrScr();
myGLCD.print("ElecFreaks.com", CENTER, 0);
myGLCD.print("EFCom GPRS", LEFT, 12);
myGLCD.print("GSM Beta V1.0", LEFT, 30);
myGLCD.update();
}
void loop()
{
int a,b;
byte addr[8];
byte addr1[5][8];
float DSTemp;
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float h;// = dht.readHumidity();
float t;// = dht.readTemperature();
// check if returns are valid, if they are NaN (not a number) then something went wrong!
if (isnan(t) || isnan(h)) {
myGLCD.clrScr();
myGLCD.print("Failed to read", LEFT, 0);
myGLCD.print("from DHT", LEFT, 9);
myGLCD.update();
//Serial.println("Failed to read from DHT");
} else {
LCDprint (h, t, 0, 0);
}
delay (250);
search_for_dses ();
ds.reset_search();
}
void search_for_dses () {
int a,b,i;
byte addr[8];
byte addr1[5][8];
while (ds.search (addr)==1) {
for (b=0; b<8; b++) {
addr1[a][b]=addr[b];
}
a++;
Serial.print ("Addr = ");
for( i = 0; i < 8; i++) {
Serial.print(addr1[a][i], HEX);
Serial.print(" ");
}
Serial.println (" ");
// DSTemp = DSmeisure(addr1);
delay (250);
}
}
float DSmeisure (byte *address1) {
byte i;
byte present = 0;
byte type_s;
byte address[8];
byte data[12];
float celsius;
ds.reset ();
ds.select (address);
// Serial.print ((addr)[8]);
// Serial.print (" ");
ds.write (0x44,1); // start conversion, with parasite power on at the end
delay (1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower () here, but the reset will take care of it.
present = ds.reset ();
ds.select (address);
ds.write (0xBE); // Read Scratchpad
for (i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read ();
}
// convert the data to actual temperature
unsigned int raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
raw = (raw & 0xFFF0) + 12 - data[6];
}
}
else {
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
}
celsius = (float)raw / 16.0;
Serial.print ("Addr = ");
for( i = 0; i < 8; i++) {
Serial.print(address[i], HEX);
Serial.print(" ");
}
Serial.print ("Temperature = ");
Serial.println (celsius);
Serial.print (" ");
Serial.flush(); //очищаем значения порта
return celsius;
}
void old ()
{
int i = 0;
char someChar[32] = {0};
if(Serial.available())
{
do{
someChar[i++] = Serial.read();
}while (Serial.available());
mySerial.print(someChar);
}
else if(mySerial.available())
{
do{
someChar[i++] = mySerial.read();
}while (Serial.available());
Serial.print(someChar);
}
}
void LCDprint (float DHTHum, float DHTTemp, float DSTemps, float DSmed)
{
String StringLCD_0="Hum: "+String(int(DHTHum))+ "."+String(getDecimal(DHTHum));
String StringLCD_1="Temp: "+String(int(DHTTemp))+ "."+String(getDecimal(DHTTemp));
String StringLCD_2="TempDS: "+String(int(DSTemps))+ "."+String(getDecimal(DSTemps));
String StringLCD_3="TempDSmed: "+String(int(DSmed))+ "."+String(getDecimal(DSmed));
myGLCD.clrScr();
myGLCD.print(String(millis()),LEFT,1);
myGLCD.print(StringLCD_0, LEFT, 10);
myGLCD.print(StringLCD_1, LEFT, 19);
myGLCD.print(StringLCD_2, LEFT, 28);
myGLCD.print(StringLCD_3, LEFT, 37);
myGLCD.update();
}
long getDecimal(float val)
{
int intPart = int(val);
long decPart = 1000*(val-intPart); //I am multiplying by 1000 assuming that the foat values will have a maximum of 3 decimal places
//Change to match the number of decimal places you need
if(decPart>0)return(decPart); //return the decimal part of float number if it is available
else if(decPart<0)return((-1)*decPart); //if negative, multiply by -1
else if(decPart=0)return(00); //return 0 if decimal part of float number is not available
}
Вот вывод с ком порта при подключенном DHT11:
ElecFreaks EFComs Start
Addr = 25 5 9 0 9 0 3D 5
Addr = B 0 B 0 9 5 E 0
Addr = E 0 0 0 0 0 0 0
Addr = 0 0 5A 14 0 0 0 0
Addr = 5A 14 0 0 0 0 0 0
Addr = 25 5 9 0 9 0 3D 5
Addr = B 0 B 0 9 5 E 0
Addr = E 0 0 0 0 0 0 0
Addr = 0 0 5A 14 0 0 0 0
Addr = 5A 14 0 0 0 0 0 0
Addr = 25 5 9 0 9 0 3D 5
Addr = B 0 B 0 9 5 E 0
Addr = E 0 0 0 0 0 0 0
Addr = 0 0 5A 14 0 0 0 0
Addr = 5A 14 0 0 0 0 0 0
Addr = 25 5 9 0 9 0 3D 5
Addr = B 0 B 0 9 5 E 0
Addr = E 0 0 0 0 0 0 0
Addr = 0 0 5A 14 0 0 0 0
Addr = 5A 14 0 0 0 0 0 0
Вот при отключенном:
ElecFreaks EFComs Start
Read failAddr = 28 FF 24 61 63 14 2 9A
Addr = 28 FF 9C 1B 63 14 2 58
Addr = 28 FF 8E 50 62 14 3 26
Addr = 28 FF 39 63 63 14 2 D
Addr = 77 BA 25 64 86 5B 65 EC
Read failAddr = 28 FF 24 61 63 14 2 9A
Addr = 28 FF 9C 1B 63 14 2 58
Addr = 28 FF 8E 50 62 14 3 26
Addr = 28 FF 39 63 63 14 2 D
Addr = 77 BA 25 64 86 5B 65 EC
Read failAddr = 28 FF 24 61 63 14 2 9A
Addr = 28 FF 9C 1B 63 14 2 58
Addr = 28 FF 8E 50 62 14 3 26
Addr = 28 FF 39 63 63 14 2 D
Addr = 77 BA 25 64 86 5B 65 EC
Вот здесь хорошо видно момент отключения датчика DHT11:
Addr = 32 5 A 0 A 0 5A 5
Addr = B 0 B 0 5A 5 E 0
Addr = E 0 0 0 0 0 0 0
Addr = 0 0 20 16 0 0 0 0
Addr = 20 16 0 0 0 0 0 0
Addr = 32 5 A 0 A 0 5A 5
Addr = B 0 B 0 5A 5 E 0
Addr = E 0 0 0 0 0 0 0
Addr = 0 0 20 16 0 0 0 0
Addr = 20 16 0 0 0 0 0 0
Addr = 32 5 A 0 A 0 5A 5
Addr = B 0 B 0 5A 5 E 0
Addr = E 0 0 0 0 0 0 0
Addr = 0 0 20 16 0 0 0 0
Addr = 20 16 0 0 0 0 0 0
Read failAddr = DF 91 F7 EB 8E E1 54 AF
Addr = 9E 66 B5 4C C5 FB 9A 1E
Addr = DE 9B E3 ED A7 F6 EF F2
Addr = 6B BF 73 EC F6 B6 6B EB
Addr = 77 BA 25 74 86 5B 65 EC
Read failAddr = 28 FF 24 61 63 14 2 9A
Addr = 28 FF 9C 1B 63 14 2 58
Addr = 28 FF 8E 50 62 14 3 26
Addr = 28 FF 39 63 63 14 2 D
Addr = 77 BA 25 74 86 5B 65 EC
Read failAddr = 28 FF 24 61 63 14 2 9A
Addr = 28 FF 9C 1B 63 14 2 58
Addr = 28 FF 8E 50 62 14 3 26
Addr = 28 FF 39 63 63 14 2 D
Addr = 77 BA 25 74 86 5B 65 EC
Read failAddr = 28 FF 24 61 63 14 2 9A
Прошу помощи. Что не так?
Заметил, что 1 из 5 датчиков DS18B20 обнаруживается неправильно : Addr = 77 BA 25 74 86 5B 65 EC - на адрес датчика вообше не похоже.
Отключил шину от arduino и включил обратно. Теперь с адресом все в порядке.
Может 5 штук - слишком много?
Может длина шины большая. Сбоит какой адрес? В смысле самый дальний датчик? Шина правильно разведена? Ответвления есть?
Может длина шины большая. Сбоит какой адрес? В смысле самый дальний датчик? Шина правильно разведена? Ответвления есть?
Датчики DS по 50 см пока на столе все собираю.
Все заработало. Правда не очень понятно чем был вызван такой эфект. Вернее не понятно совсем.
Просто в функции search_for_dses индекс а добавлялся раньше чем положено.
Код теперь выглядит так:
#include <OneWire.h> #include "DHT.h" #include <LCD5110_Graph.h> #include <SoftwareSerial.h> #define DHTPIN 5 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); OneWire ds (4); // все OneWire устройства на pin 4 //int led_pin=13; // определили pin 13 для светодиода byte done[8]; LCD5110 myGLCD(9,10,11,12,13); extern uint8_t SmallFont[]; #define rxPin 2 #define txPin 3 SoftwareSerial mySerial(rxPin, txPin); void setup() { dht.begin(); myGLCD.InitLCD(); myGLCD.setFont(SmallFont); mySerial.begin(19200); // the GPRS baud rate Serial.begin(19200); // the Serial port baud rate Serial.println("ElecFreaks EFComs Start"); myGLCD.clrScr(); myGLCD.print("ElecFreaks.com", CENTER, 0); myGLCD.print("EFCom GPRS", LEFT, 12); myGLCD.print("GSM Beta V1.0", LEFT, 30); myGLCD.update(); } void loop() { int a,b; byte addr[8]; byte addr1[5][8]; float DSTemp; // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) float h = dht.readHumidity(); float t = dht.readTemperature(); // check if returns are valid, if they are NaN (not a number) then something went wrong! if (isnan(t) || isnan(h)) { myGLCD.clrScr(); myGLCD.print("Failed to read", LEFT, 0); myGLCD.print("from DHT", LEFT, 9); myGLCD.update(); //Serial.println("Failed to read from DHT"); } else { LCDprint (h, t, 0, 0); } delay (1000); search_for_dses (); ds.reset_search(); } void search_for_dses () { int a,b,i; byte addr[8]; byte addr1[5][8]; while (ds.search (addr)==1) { for (b=0; b<8; b++) { addr1[a][b]=addr[b]; } Serial.print ("Addr = "); for( i = 0; i < 8; i++) { Serial.print(addr1[a][i], HEX); Serial.print(" "); } Serial.println (" "); // DSTemp = DSmeisure(addr1); delay (250); a++; } } float DSmeisure (byte *address1) { byte i; byte present = 0; byte type_s; byte address[8]; byte data[12]; float celsius; ds.reset (); ds.select (address); // Serial.print ((addr)[8]); // Serial.print (" "); ds.write (0x44,1); // start conversion, with parasite power on at the end delay (1000); // maybe 750ms is enough, maybe not // we might do a ds.depower () here, but the reset will take care of it. present = ds.reset (); ds.select (address); ds.write (0xBE); // Read Scratchpad for (i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read (); } // convert the data to actual temperature unsigned int raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms } celsius = (float)raw / 16.0; Serial.print ("Addr = "); for( i = 0; i < 8; i++) { Serial.print(address[i], HEX); Serial.print(" "); } Serial.print ("Temperature = "); Serial.println (celsius); Serial.print (" "); Serial.flush(); //очищаем значения порта return celsius; } void old () { int i = 0; char someChar[32] = {0}; if(Serial.available()) { do{ someChar[i++] = Serial.read(); }while (Serial.available()); mySerial.print(someChar); } else if(mySerial.available()) { do{ someChar[i++] = mySerial.read(); }while (Serial.available()); Serial.print(someChar); } } void LCDprint (float DHTHum, float DHTTemp, float DSTemps, float DSmed) { String StringLCD_0="Hum: "+String(int(DHTHum))+ "."+String(getDecimal(DHTHum)); String StringLCD_1="Temp: "+String(int(DHTTemp))+ "."+String(getDecimal(DHTTemp)); String StringLCD_2="TempDS: "+String(int(DSTemps))+ "."+String(getDecimal(DSTemps)); String StringLCD_3="TempDSmed: "+String(int(DSmed))+ "."+String(getDecimal(DSmed)); myGLCD.clrScr(); myGLCD.print(String(millis()),LEFT,1); myGLCD.print(StringLCD_0, LEFT, 10); myGLCD.print(StringLCD_1, LEFT, 19); myGLCD.print(StringLCD_2, LEFT, 28); myGLCD.print(StringLCD_3, LEFT, 37); myGLCD.update(); } long getDecimal(float val) { int intPart = int(val); long decPart = 1000*(val-intPart); //I am multiplying by 1000 assuming that the foat values will have a maximum of 3 decimal places //Change to match the number of decimal places you need if(decPart>0)return(decPart); //return the decimal part of float number if it is available else if(decPart<0)return((-1)*decPart); //if negative, multiply by -1 else if(decPart=0)return(00); //return 0 if decimal part of float number is not available }Вот странность то!
Если раскомментировать стройки между =============, все работает как надо, а в таком виде вместо показаний температуры показывает 4095.93, а как только включаешь порт монитор, то начинает работать нормально. Может кто-нибудь знает где связь между 1-wire и выводом в серийный порт?
#include <OneWire.h> #include "DHT.h" #include <LCD5110_Graph.h> #include <SoftwareSerial.h> #define DHTPIN 5 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); OneWire ds (4); // все OneWire устройства на pin 4 //int led_pin=13; // определили pin 13 для светодиода byte done[8]; LCD5110 myGLCD(9,10,11,12,13); extern uint8_t SmallFont[]; #define rxPin 2 #define txPin 3 SoftwareSerial mySerial(rxPin, txPin); void setup() { dht.begin(); myGLCD.InitLCD(); myGLCD.setFont(SmallFont); mySerial.begin(19200); // the GPRS baud rate Serial.begin(19200); // the Serial port baud rate Serial.println("ElecFreaks EFComs Start"); myGLCD.clrScr(); myGLCD.print("ElecFreaks.com", CENTER, 0); myGLCD.print("EFCom GPRS", LEFT, 12); myGLCD.print("GSM Beta V1.0", LEFT, 30); myGLCD.update(); } void loop() { int a,b; byte addr[8]; byte addr1[5][8]; float DSTemp; float DSmed; // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) float h = dht.readHumidity(); float t = dht.readTemperature(); // check if returns are valid, if they are NaN (not a number) then something went wrong! if (isnan(t) || isnan(h)) { myGLCD.clrScr(); myGLCD.print("Failed to read", LEFT, 0); myGLCD.print("from DHT", LEFT, 9); myGLCD.update(); //Serial.println("Failed to read from DHT"); } delay (1000); DSmed=search_for_dses (); LCDprint (h, t, 0, DSmed); ds.reset_search(); } float search_for_dses () { int a,b,i; byte addr[8]; byte addr1[5][8]; float DSTemp[5]; float DSTempmed; float DSTempsum; while (ds.search (addr)==1) { for (b=0; b<8; b++) { addr1[a][b]=addr[b]; } //====================================== //Serial.print ("Addr = "); //for( i = 0; i < 8; i++) { // Serial.print(addr1[a][i], HEX); // Serial.print(" "); //} //Serial.println (" "); //====================================== delay (250); a++; } for ( a=0; a<5; a++) { DSTemp[a] = DSmeisure(addr1[a]); DSTempsum+=DSTemp[a]; //Serial.println (DSTemp[a]); } DSTempmed=DSTempsum/5; Serial.println (DSTempmed); return DSTempmed; } float DSmeisure (byte *address) { byte i; byte present = 0; byte type_s; byte data[12]; float celsius; ds.reset (); ds.select (address); // Serial.print ((addr)[8]); // Serial.print (" "); ds.write (0x44,1); // start conversion, with parasite power on at the end delay (1000); // maybe 750ms is enough, maybe not // we might do a ds.depower () here, but the reset will take care of it. present = ds.reset (); ds.select (address); ds.write (0xBE); // Read Scratchpad for (i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read (); } // convert the data to actual temperature unsigned int raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms } celsius = (float)raw / 16.0; //Serial.print ("Addr = "); //for( i = 0; i < 8; i++) { // Serial.print(address[i], HEX); // Serial.print(" "); //} Serial.print ("Temperature = "); Serial.println (celsius); Serial.print (" "); //Serial.flush(); //очищаем значения порта return celsius; } void old () { int i = 0; char someChar[32] = {0}; if(Serial.available()) { do{ someChar[i++] = Serial.read(); }while (Serial.available()); mySerial.print(someChar); } else if(mySerial.available()) { do{ someChar[i++] = mySerial.read(); }while (Serial.available()); Serial.print(someChar); } } void LCDprint (float DHTHum, float DHTTemp, float DSTemps, float DSmed) { String StringLCD_0="Hum:"+String(int(DHTHum))+ "."+String(getDecimal(DHTHum)); String StringLCD_1="Temp:"+String(int(DHTTemp))+ "."+String(getDecimal(DHTTemp)); String StringLCD_2="TDS:"+String(int(DSTemps))+ "."+String(getDecimal(DSTemps)); String StringLCD_3="TDSmed:"+String(int(DSmed))+ "."+String(getDecimal(DSmed)); myGLCD.clrScr(); myGLCD.print(String(millis()),LEFT,1); myGLCD.print(StringLCD_0, LEFT, 10); myGLCD.print(StringLCD_1, LEFT, 19); myGLCD.print(StringLCD_2, LEFT, 28); myGLCD.print(StringLCD_3, LEFT, 37); myGLCD.update(); } long getDecimal(float val) { int intPart = int(val); long decPart = 1000*(val-intPart); //I am multiplying by 1000 assuming that the foat values will have a maximum of 3 decimal places //Change to match the number of decimal places you need if(decPart>0)return(decPart); //return the decimal part of float number if it is available else if(decPart<0)return((-1)*decPart); //if negative, multiply by -1 else if(decPart=0)return(00); //return 0 if decimal part of float number is not available }Причем, когда раскомментарено, сразу после загрузки скетча в плату не работает (4095,93). резет кнопкой и все работает как надо. Если порт монитор включить, тоже работает правда перезагружается сама. При последующих включениях по питанию сразу работает как надо.
При нармальной работе при подключении порт монитор ребутается и работает нормально.
Я с ардуино недавно общаюсь. Она глючная?
Причем, когда раскомментарено, сразу после загрузки скетча в плату не работает (4095,93). резет кнопкой и все работает как надо. Если порт монитор включить, тоже работает правда перезагружается сама. При последующих включениях по питанию сразу работает как надо.
При нармальной работе при подключении порт монитор ребутается и работает нормально.
Я с ардуино недавно общаюсь. Она глючная?
А с какой целью вы 1. Считываете каждый проход адреса по новой?. 2. Зачем даете команду на конвертацию температуры поадресно? 3.Какой смысл в среднем арифметическом с разных датчиков?
Датчики подключены по 2-х или 3-х проводной схеме?
Что то больше похоже на програмный глюк.
1. Я хотел сделать, чтобы датчики можно было менять не внося изменений в код. Каждый цикл - погорячился конечно. Надо сделать, чтобы функция поиска вызывалась периодически возвращала массив адресов.
2. Конвертация перекочевала из примера от производителя датчиков.
3. Просто на экране пока заложена только 1 строчка для температуры с датчиков. (И еще на разобрался как возвращать массив из функции)
4. Датчики подключены по 3 х проводной схеме. (земля, 5 вольт, 5 вольт - резистор 4,7кОм - дата(пин)).
Убрал вывод из поиска инициализацию майсериал тоже. Все равно датчики выдают 4095,94.
#include <OneWire.h> #include "DHT.h" #include <LCD5110_Graph.h> //#include <SoftwareSerial.h> #define DHTPIN 5 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); OneWire ds (4); // все OneWire устройства на pin 4 //int led_pin=13; // определили pin 13 для светодиода byte done[8]; LCD5110 myGLCD(9,10,11,12,13); extern uint8_t SmallFont[]; //#define rxPin 2 //#define txPin 3 //SoftwareSerial mySerial(rxPin, txPin); void setup() { dht.begin(); myGLCD.InitLCD(); myGLCD.setFont(SmallFont); // mySerial.begin(19200); // the GPRS baud rate Serial.begin(19200); // the Serial port baud rate Serial.println("ElecFreaks EFComs Start"); myGLCD.clrScr(); myGLCD.print("Hello world!", CENTER, 0); myGLCD.print("EFCom GPRS", LEFT, 12); myGLCD.print("GSM Beta V1.0", LEFT, 30); myGLCD.update(); } void loop() { int a,b; byte addr[8]; byte addr1[5][8]; float DSTemp; float DSmed; // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) float h = dht.readHumidity(); float t = dht.readTemperature(); delay (2000); // check if returns are valid, if they are NaN (not a number) then something went wrong! if (isnan(t) || isnan(h)) { myGLCD.clrScr(); myGLCD.print("Failed to read", LEFT, 0); myGLCD.print("from DHT", LEFT, 9); myGLCD.update(); //Serial.println("Failed to read from DHT"); } delay (1000); DSmed=search_for_dses (); LCDprint (h, t, 0, DSmed); ds.reset_search(); } float search_for_dses () { int a,b,i; byte addr[8]; byte addr1[5][8]; float DSTemp[5]; float DSTempmed; float DSTempsum; while (ds.search (addr)==1) { for (b=0; b<8; b++) { addr1[a][b]=addr[b]; } //====================================== // Serial.print ("Addr = "); // for( i = 0; i < 8; i++) { // Serial.print(addr1[a][i], HEX); // Serial.print(" "); // } // Serial.println (" "); //====================================== delay (1000); a++; } for ( a=0; a<5; a++) { DSTemp[a] = DSmeisure(addr1[a]); DSTempsum+=DSTemp[a]; //Serial.println (DSTemp[a]); } DSTempmed=DSTempsum/5; Serial.println (DSTempmed); return DSTempmed; } float DSmeisure (byte *address) { byte i; byte present = 0; byte type_s; byte data[12]; float celsius; ds.reset (); ds.select (address); // Serial.print ((addr)[8]); // Serial.print (" "); ds.write (0x44,1); // start conversion, with parasite power on at the end delay (1000); // maybe 750ms is enough, maybe not // we might do a ds.depower () here, but the reset will take care of it. present = ds.reset (); ds.select (address); ds.write (0xBE); // Read Scratchpad for (i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read (); } // convert the data to actual temperature unsigned int raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms } celsius = (float)raw / 16.0; //Serial.print ("Addr = "); //for( i = 0; i < 8; i++) { // Serial.print(address[i], HEX); // Serial.print(" "); //} Serial.print ("Temperature = "); Serial.println (celsius); Serial.print (" "); //Serial.flush(); //очищаем значения порта return celsius; } //void old () //{ // int i = 0; // char someChar[32] = {0}; // if(Serial.available()) // { // do{ // someChar[i++] = Serial.read(); // }while (Serial.available()); // mySerial.print(someChar); // } // else if(mySerial.available()) // { // do{ // someChar[i++] = mySerial.read(); // }while (Serial.available()); // Serial.print(someChar); // } //} void LCDprint (float DHTHum, float DHTTemp, float DSTemps, float DSmed) { String StringLCD_0="Hum:"+String(int(DHTHum))+ "."+String(getDecimal(DHTHum)); String StringLCD_1="Temp:"+String(int(DHTTemp))+ "."+String(getDecimal(DHTTemp)); String StringLCD_2="RIR:"+String(int(DSTemps))+ "."+String(getDecimal(DSTemps)); String StringLCD_3="TDSmed:"+String(int(DSmed))+ "."+String(getDecimal(DSmed)); myGLCD.clrScr(); myGLCD.print(String(millis()),LEFT,1); myGLCD.print(StringLCD_0, LEFT, 10); myGLCD.print(StringLCD_1, LEFT, 19); myGLCD.print(StringLCD_2, LEFT, 28); myGLCD.print(StringLCD_3, LEFT, 37); myGLCD.update(); } long getDecimal(float val) { int intPart = int(val); long decPart = 100*(val-intPart); //I am multiplying by 1000 assuming that the foat values will have a maximum of 3 decimal places //Change to match the number of decimal places you need if(decPart>0)return(decPart); //return the decimal part of float number if it is available else if(decPart<0)return((-1)*decPart); //if negative, multiply by -1 else if(decPart=0)return(00); //return 0 if decimal part of float number is not available }Закомментарил. Вот вывод в порт На LCD тоже 4095.93:
А вот ножку D отсоединил от DHT:
1. Опрос адресов сделайте один раз в Setup-е. Дальше им пользуйтесь.
2.Конвертацию проще задать для всех пяти -
ds.reset();
ds.write(0xCC); //Команда инициации
ds.write(0x44); //Команда на конвертирование
Это строки с 110 по 116. В 116 единичка была нужна для паразитного питания. Эту функцию вызываете один раз и через 750мС можете со всех датчиков взять температуру.
3. Массив из функции вернется сам, если задать его как глобальную переменную.
Упростите сперва код по максимуму и выкиньте все лишние действия, а потом уже гонять.
Да и переменные, которые вы несколько раз переопределяете, выберите которые должны быть глобальными, пусть ими и будут.
Сложно как то у тебя все... ни к чему это все. У меня 3 датчика DS18B20 и один DHT11, замеры температур происходит раз в две минуты, и все ок.
вот http://arduino.ru/forum/proekty/sistema-umnyi-dom-dlya-zagorodnogo-doma-na-arduino-mega2560-hc-05-sim900dht113-kh-ds18
Сложно как то у тебя все... ни к чему это все. У меня 3 датчика DS18B20 и один DHT11, замеры температур происходит раз в две минуты, и все ок.
вот http://arduino.ru/forum/proekty/sistema-umnyi-dom-dlya-zagorodnogo-doma-na-arduino-mega2560-hc-05-sim900dht113-kh-ds18
Так я и говорю, что проблема скорее всего в этом компоте.
Спасибо за советы.
Все по делу.
Новый прикол.
#include <OneWire.h> OneWire ds (4); byte DSaddresses[5][8]; // массив адресов датчиков DS18B20 void setup() { Serial.begin(19200); Serial.println("Start"); search_for_dses (); Serial.println("Setup complete"); } void loop() { int a,i; for( a=0; a < 5; a++) { Serial.print ("Addr = "); for( i = 0; i < 8; i++) { Serial.print(DSaddresses[a][i], HEX); Serial.print(" "); } Serial.println (" "); } delay (1000); } void search_for_dses () { int a,b,i; byte addr[8]; Serial.println ("Serching for DS"); while (ds.search (addr)==1) { for (b=0; b<8; b++) { DSaddresses[a][b]=addr[b]; } //====================================== Serial.print ("Addr = "); for( i = 0; i < 8; i++) { Serial.print(DSaddresses[a][i], HEX); Serial.print(" "); } Serial.println (" "); //====================================== delay (250); a++; } }#include <OneWire.h> OneWire ds (4); byte DSaddresses[5][8]; // массив адресов датчиков DS18B20 void setup() { Serial.begin(19200); Serial.println("Start"); search_for_dses (); Serial.println("Setup complete"); } void loop() { int a,i; for( a=0; a < 5; a++) { Serial.print ("Addr = "); for( i = 0; i < 8; i++) { Serial.print(DSaddresses[a][i], HEX); Serial.print(" "); } Serial.println (" "); } delay (1000); } void search_for_dses () { int a,b,i; byte addr[8]; Serial.println ("Serching for DS"); while (ds.search (addr)==1) { for (b=0; b<8; b++) { DSaddresses[a][b]=addr[b]; } //====================================== // Serial.print ("Addr = "); // for( i = 0; i < 8; i++) { // Serial.print(DSaddresses[a][i], HEX); // Serial.print(" "); // } // Serial.println (" "); //====================================== delay (250); a++; } }Это явно глюк компилятора. 1.0.6
Завтра попробую поюзать, х-ня какая то.
Там ответил. http://arduino.ru/forum/proekty/sistema-umnyi-dom-dlya-zagorodnogo-doma-...
Переделаю счетчики в циклах на byte вечером.
Переделаю счетчики в циклах на byte вечером.
Вы лучше сразу определитесь со всеми переменными, их типами и областями видимости. http://arduino.ru/Tutorial/Variables
Не забываем, что в процессе вычислений переменная может неявно изменить свой тип.
Более толково про это может старшие товарищи расскажут.
Переделаю счетчики в циклах на byte вечером.
Вы лучше сразу определитесь со всеми переменными, их типами и областями видимости. http://arduino.ru/Tutorial/Variables
Не забываем, что в процессе вычислений переменная может неявно изменить свой тип.
Более толково про это может старшие товарищи расскажут.
Спасибо за информацию.
Можешь привести пример когда переменная может неявно изменить свой тип?
Где то попадалось, что пытается принять тип приближенный к типу полученному в результате выполнения выражения. Сейчас уже не найду. Основное, когда что то идет не так, проверить принимаемые значения используемых переменных. Собака там роется весьма часто. Почему у вас колбасило переменную "а", вразумительно объяснить не могу.
Часть проблемы нашел. Лебедев.М.Б. CodeVisionAVR "Локальные переменные - это переменные доступные только в функциях, где они объявлены. Локальные переменные при вызове функции автоматически не инициализируются и могут содержать всякий мусор."
Где то попадалось, что пытается принять тип приближенный к типу полученному в результате выполнения выражения. Сейчас уже не найду. Основное, когда что то идет не так, проверить принимаемые значения используемых переменных. Собака там роется весьма часто. Почему у вас колбасило переменную "а", вразумительно объяснить не могу.
Ввел я вас немного в блуд, это происходит в скрытой от вас форме в процессе вычислений. А вот результаты этой математики могут быть весьма поразительными. Компилятор спокойно скушает byte a=90000; , а итог сами проверьте.
Да. Вы правы. переменная а, видимо, содержала мусор. Я задал ее явно при инициализации и все заработало как надо.
сейчас код выгладит так:
#include "DHT.h" #include <OneWire.h> #define DHTPIN 5 #define DHTTYPE DHT11 #define PIRpin 6 // пин датчика движения OneWire ds (4); DHT dht(DHTPIN, DHTTYPE); byte DSaddresses[5][8]; // массив адресов датчиков DS18B20 float Celsius[5]; // массив измерений датчиков DS18B20 float DHThum=0; // DHT влажность float DHTtemp=0; // DHT температура int minSecsBetweenSMS = 60; // 1 min long lastSend = 0; // Last SMS time; long delta = minSecsBetweenSMS * 1000; // inSecsBetweenSMS millisecs void setup() { Serial.begin(19200); Serial.println("Start"); pinMode(PIRpin, INPUT); // определяем RIRpin как прин ввода Serial.println("Starting DHT"); dht.begin(); search_for_dses (); Serial.println("Setup complete"); } void loop() { /* int a,i; for( a=0; a < 5; a++) { Serial.print ("Addr = "); for( i = 0; i < 8; i++) { Serial.print(DSaddresses[a][i], HEX); Serial.print(" "); } Serial.println (" "); } */ long now = millis(); if (PIRcheck (now)==true) { Serial.println("RIR ALARM"); Serial.println("Sending SMS(emeil)"); } DSmeasure (); DHTmeasure (); delay (1000); } void search_for_dses () { byte a=0,b=0; byte addr[8]; Serial.println ("Serching for DS"); while (ds.search (addr)==1) { for (b=0; b<8; b++) { DSaddresses[a][b]=addr[b]; } /* //====================================== Serial.print ("a= "); Serial.print (a); Serial.print (" Addr = "); for( b = 0; b < 8; b++) { Serial.print(DSaddresses[a][b], HEX); Serial.print(" "); } Serial.println (" "); */ //====================================== delay (250); a++; } } void DSmeasure () { byte a,b; byte present = 0; byte data[12]; Serial.println ("Starting measurments"); ds.reset(); ds.write(0xCC); // select all ds.write(0x44); // convert T for all devices Serial.println ("wait 1000 mSec"); delay (1000); present = ds.reset(); for (a=0; a<5 ; a++) { present = ds.reset(); ds.select(DSaddresses[a]); ds.write(0xBE); for ( b = 0; b < 9; b++) //Get 9 bytes { data[b] = ds.read(); Serial.print(data[b], HEX); Serial.print(" "); } Serial.print(" CRC="); Serial.print( OneWire::crc8( data, 8), HEX); // convert the data to actual temperature unsigned int raw = (data[1] << 8) | data[0]; byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw << 3; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms Celsius[a] = (float)raw / 16.0; Serial.print(" C="); Serial.print(Celsius[a]); Serial.println(); } Serial.println ("Measurments completed"); } void DHTmeasure() { // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) DHThum = 0; DHTtemp = 0; DHThum = dht.readHumidity(); DHTtemp = dht.readTemperature(); Serial.print("Hum="); Serial.print(DHThum); Serial.print(","); Serial.print("Temp="); Serial.print(DHTtemp); Serial.println(); } boolean PIRcheck (long TimeOfCheck) { if (digitalRead(PIRpin) == HIGH) { if ( TimeOfCheck >= (lastSend + delta)) // Check for enough time has passed after last HIGH { Serial.println("MOVEMENT"); Serial.println(delta); Serial.println(lastSend); lastSend = TimeOfCheck; Serial.println(lastSend); return true; } else { Serial.println("SMS canceled cause = too soon"); return false; } } return false; }В сериал порту следующее:
Да это не я, а учебник AVRа. Кстати глобальные сами инициализируются 0.
А код дальше чистите, delay() повыкидывайте, строки ненужные и пр.
Еще прикол в подтверждение мусора при приведении типов:
строка 016 delta умножаю положительное int на положительное число и кладу в лонг. в результате delta принимает непонятное отридцательное значение.
переделал int на long.
Еще прикол в подтверждение мусора при приведении типов:
строка 016 delta умножаю положительное int на положительное число и кладу в лонг. в результате delta принимает непонятное отридцательное значение.
переделал int на long.
Судя по множителю, вы здесь за пределы int-а ушли, вот и поразительный результат.
Грабли сплошные.
Я присваиваю longу значение inta умноженного на int число. Компилятор должен увидеть, что я результат хочу положить в лонг и понять. А получается, что он просто берет int, копирует его, умножает, а уже переполненый результат пишет в лонг.
Приведите первый инт к лонгу и переполнения не будет. Где то про это уже была тема.
Грабли сплошные.
Я присваиваю longу значение inta умноженного на int число. Компилятор должен увидеть, что я результат хочу положить в лонг и понять. А получается, что он просто берет int, копирует его, умножает, а уже переполненый результат пишет в лонг.
Для него в данном случае приоритет стоит на правую часть. Он и работает с int-ами, как умеет. Если бы один из множителей был long-ом и получаемое значение long или float, проблемы бы тоже не было. Значит сразу прикидывать какой диапазон может принять значение и под него назначать тип переменных.
И тему поищите, мне тоже кажется, что где-то здесь видел. Наверно поэтому и не было такого вопроса.
Похоже происходит следующее: компилятор видит два числа по два байта, резервирует под результат два байта, производит вычисление, кладет результат в два зарезервированных байта и после этого производит присваиваивание этого результата. Пока идут все эти шаги он не смотрит на левую часть. Соответственно если одно из чисел справа будет четырехбайтовым он зарезервирует четыре байта. Но если потом слева окажется двухбайтовая переменная он эти четыре запихает в ее два. Вот и поразительный результат.
Прямо Фрейд какой-то))))
Вас почитаешь, так прям страшно становится :) Компилятор не один проход делает, выделить память правильного размера под переменную, это для него одна из первых задач. А вот бездумное использование буферов последовательного порта - проблема программера. Мне вот просто интересно, вы когда в последовательный порт данными кидаетесь, вы себе что представляете... ну как эти данные обрабатываются, куда складываются, как и как быстро отправляются ? Может вам руководство почитать да и увеличить размер буфера отправки последовательного порта, или скорость например ?
Вас почитаешь, так прям страшно становится :) Компилятор не один проход делает, выделить память правильного размера под переменную, это для него одна из первых задач. А вот бездумное использование буферов последовательного порта - проблема программера. Мне вот просто интересно, вы когда в последовательный порт данными кидаетесь, вы себе что представляете... ну как эти данные обрабатываются, куда складываются, как и как быстро отправляются ? Может вам руководство почитать да и увеличить размер буфера отправки последовательного порта, или скорость например ?
Ну так основная масса здесь и собралась, чтобы понять эти процессы. Я попытался объяснить как сам понимаю эту проблему, т.к. больше никто не берется. Только когда я учился, кибернетика еще была продажной девкой империализма, а програмирование логарифмической линейкой. И если вы зная больше, возьмете на себя труд объяснить эти механизмы, доходчиво для дилетантов, то все будут только благодарны. Основной массе присутствующих академические знания не нужны. Достаточно знать, что делать нельзя и почему. Раньше это хорошо делал leshak, но куда то исчез. (((
Я представляю себя руководителем предприятия (ну или королем небольшой страны) и пользуясь своими полномочиями, издаю приказы (типа Serial.print (советники - IDE подкрашивает)), и кидаюсь распоряжениями)). Народ, вывести в порт "бла, бла, бла"! Если приказ непосилен для народа, то советники перед передачей исполнителям должны сообщить мне об этом. Если дума - советники пропустили (разноцветный приказ), то значит инструкции ассемблера (служащие) должны заставить народ выполнить!
Буферы портов (планирую использовать 3 порта) - это грядущие грабли. планирую подключить sim900 и оба по серийным портам))
Видимо, придется вести себя как сапер, а не как король((
Я король! Почему мне приходится вникать из чего сделаны шахматы?))))))
Ну я то же не молод :) У меня уже сынок институт закончил. Попробую разжевать. Скорость отправки одного байта по последовательному интерфейсу конечна. Если UART сконфигурирован на 9600 бод, то передача одного символа займет примерно 10/9600 сек, передача строки из листинга (40*10)/9600 = 0.042 СЕКУНДЫ. Если пихать в буфер данные быстерее чем 1000 символов в секунду, то произойдет переполнение, которое либо приведет в выходу буфера отправки за пределы отведенной памяти и затиранию других переменных, которые компилятор разместил в соседних ячейках, либо выводу в порт бреда. По уммолчанию библиотека последовательного интерфейса сконфигурирована всего на 16 байт, это всего 8 символов ! Так что копать нужно именно в сторону протоколирования, то есть вывода в монитор.
Кстати, при нормальном объявлении переменной компилятор обнуляет выделенную область, иными словами:
int a и int a = 0 два идентичных объявление переменной. Непроинициализированной переменная может оказаться только если вы объявите указатель на нее, а потом попробуете ее протитать по этому указателю.
При неявных преобразованиях типов компилятор ведет себя не предсказуемо, иными словами:
long r;
int a,b;
r=a+b и r=(long)a + (long)b могут дать различные результаты.
Я же говорю, достаточно чего нибудь почитать :)
Может потому, что король голый ? У королей над ардуиной нет советников, есть только народ.
Если говорить про программный (а не аппаратный) последовательный интерфейс, то тут все проще, поскольку при работе через програмный на время передачи данных процессор не освобождается, то можно не боятся переполнения буфера. Аппаратная отправка байта подразумевает закладку байта в регистр и изменение бита старта передачи и возврат в программу, хотя байт еще передпн не полностью, а програмная будет таймингами дергать ногу пока байт не передастся полностью, поэтому во втором случае буфера просто нет :)
Ну вообще круто!
Придется снять корону, выделить несколько нейронов своего мозга и присоединить их через токопроводящий гель к пинам микроконтроллера) Хотя это бесполезно... Все происходит внутри него..
Придется читать мунускрипты. Зато это можно делать и в короне, хоть и голышом))
int a и int a = 0 два идентичных объявление переменной. Непроинициализированной переменная может оказаться только если вы объявите указатель на нее, а потом попробуете ее протитать по этому указателю.
Не вводите народ в заблуждение! :)
Совершенно правильно кто-то выше писал - инициализируются глобальные переменные, а локальные - нет.
Не совсем уверен насчёт статических локальных. Кажется, они тоже инициализируются нулями.
long r;
int a,b;
r=a+b и r=(long)a + (long)b могут дать различные результаты.
На самом деле, вполне предсказуемо, и правила там достаточно чёткие... но обычно их никто не помнит. :)
Поэтому, да, в сомнительных случаях лучше указывать тип операндов явно.
Опять же, так можно говорить только про какую-то конкретную программную реализацию.
В другой реализации разработчик вполне может организовать такой же буфер для данных, и такую же "фоновую" передачу по прерываниям. Кстати, по-хорошему, так оно и должно делаться.
r=a+b и r=(long)a + (long)b могут дать различные результаты.
Вполне достаточно написать:
Насчёт сложений/умножений правила примерно такие:
Операнды приводятся к одному типу. Выбирается тип операнда, дающий большую точность, но при этом не меньше чем int.
Результат операции будет иметь такой же тип.
Операция присваивания - это следующая, отдельная операция, со своими правилами. Там компилятор уже готовый результат приводит к нужному типу.
Это так, по памяти, могу немного ошибаться. Если что - прошу поправить.
Вообще, заработало именно когда, присвоил значение переменной перед обрещении к ней. И когда она была int и когда стала byte.
Я выводил переменную "а" в серийный порт и ее значения были корректны 0,1,2,3,4 и при этом все работало как надо. Не работало только когда я не выводил "а" в серийный порт.
Пробовал просто ерунду выводить в порт (не работает). Работает только когда вывожу "а" в порт, или задаю ее до первого обращения к ней. До вывода в порт "а" принимает значение, которое знает только микроконтроллер))).
Вы два примера покажите. А так по "голословию" я могу мульон предположений сделать почему, да отчего.
Не вводите народ в заблуждение! :)
Совершенно правильно кто-то выше писал - инициализируются глобальные переменные, а локальные - нет.
Не совсем уверен насчёт статических локальных. Кажется, они тоже инициализируются нулями.
"Где ж ты раньше был, целовался с кем ?" Это общепринятые правила СИ. Компилятор задействованый под ардуино иногда поступает по своему :) Копались в полученых, после компилляции кодах ? Рекомендую :)
Опять же, так можно говорить только про какую-то конкретную программную реализацию.
В другой реализации разработчик вполне может организовать такой же буфер для данных, и такую же "фоновую" передачу по прерываниям. Кстати, по-хорошему, так оно и должно делаться.
Разумнее было бы, то что вы написали обзывать програмно-аппаратной реализацией, к тому же она ближе к аппаратной, будьте вдумчевее, не пытайтесь поймать меня "за язык" :)
[Вполне достаточно написать:
Полностью согласен.
Насчёт сложений/умножений правила примерно такие:
Операнды приводятся к одному типу. Выбирается тип операнда, дающий большую точность, но при этом не меньше чем int.
Результат операции будет иметь такой же тип.
Операция присваивания - это следующая, отдельная операция, со своими правилами. Там компилятор уже готовый результат приводит к нужному типу.
Это так, по памяти, могу немного ошибаться. Если что - прошу поправить.
Не вводите людей в заблуждение.
int a,
byte b=255;
byte c=255;
a = c + b;
У вас получится 510 ? Сильно сомневаюсь :)
a=(int)b+c, уверен будет 510.
Насчёт сложений/умножений правила примерно такие:
Операнды приводятся к одному типу. Выбирается тип операнда, дающий большую точность, но при этом не меньше чем int.
Результат операции будет иметь такой же тип.
Операция присваивания - это следующая, отдельная операция, со своими правилами. Там компилятор уже готовый результат приводит к нужному типу.
Это так, по памяти, могу немного ошибаться. Если что - прошу поправить.
Не вводите людей в заблуждение.
int a,
byte b=255;
byte c=255;
a = c + b;
У вас получится 510 ? Сильно сомневаюсь :)
a=(int)b+c, уверен будет 510.
Вы знаете, получилось((
int a; byte b=255; byte c=255; void setup() {Serial.begin(9600); } void loop() { a=b+c; Serial.println(a,DEC); delay(2000); }С умножением такой номер не проходит.
Погорячился, со значениями в и с =181, халява проходит. И полность проходит если a - unsigned int.