Одновременная работа нескольких DS18B20 и DHT11

dimontie
Offline
Зарегистрирован: 11.01.2015

Здравствуйте.

Странная проблема с обнаружением устройств на шине 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  
 
Прошу помощи. Что не так?
 
dimontie
Offline
Зарегистрирован: 11.01.2015

Заметил, что 1 из 5 датчиков DS18B20 обнаруживается неправильно : Addr = 77 BA 25 74 86 5B 65 EC  - на адрес датчика вообше не похоже.

Отключил шину от arduino и включил обратно. Теперь с адресом все в порядке.

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 = 28 FF 8E 50 62 14 3 26
 
Но при подключении DHT11:
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 = 28 FF 8E 50 62 14 3 26
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
 

Может 5 штук - слишком много?

 
 
kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Может длина шины большая. Сбоит какой адрес? В смысле самый дальний датчик? Шина правильно разведена? Ответвления есть?

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Может длина шины большая. Сбоит какой адрес? В смысле самый дальний датчик? Шина правильно разведена? Ответвления есть?

dimontie
Offline
Зарегистрирован: 11.01.2015

Датчики 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
}

 

dimontie
Offline
Зарегистрирован: 11.01.2015

dimontie
Offline
Зарегистрирован: 11.01.2015

Вот странность то!

Если раскомментировать стройки между =============, все работает как надо, а в таком виде вместо показаний температуры показывает 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
}

 

dimontie
Offline
Зарегистрирован: 11.01.2015

Причем, когда раскомментарено, сразу после загрузки скетча в плату не работает (4095,93). резет кнопкой и все работает как надо. Если порт монитор включить, тоже работает правда перезагружается сама. При последующих включениях по питанию сразу работает как надо.

При нармальной работе при подключении порт монитор ребутается и работает нормально.

Я с ардуино недавно общаюсь. Она глючная?

bwn
Offline
Зарегистрирован: 25.08.2014

dimontie пишет:

Причем, когда раскомментарено, сразу после загрузки скетча в плату не работает (4095,93). резет кнопкой и все работает как надо. Если порт монитор включить, тоже работает правда перезагружается сама. При последующих включениях по питанию сразу работает как надо.

При нармальной работе при подключении порт монитор ребутается и работает нормально.

Я с ардуино недавно общаюсь. Она глючная?

А с какой целью вы 1. Считываете каждый проход адреса по новой?. 2. Зачем даете команду на конвертацию температуры поадресно? 3.Какой смысл в среднем арифметическом с разных датчиков?

Датчики подключены по 2-х или 3-х проводной схеме?

Что то больше похоже на програмный глюк.

dimontie
Offline
Зарегистрирован: 11.01.2015

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: 

ElecFreaks EFComs Start
Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 4095.94
Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 4095.94
 
dimontie
Offline
Зарегистрирован: 11.01.2015

А вот ножку D отсоединил от DHT:

Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 Temperature = 4095.94
 4095.94
Read failTemperature = 25.06
 Temperature = 25.19
 Temperature = 25.12
 Temperature = 25.25
 Temperature = 25.12
 25.15
Read fail

 

bwn
Offline
Зарегистрирован: 25.08.2014

1. Опрос адресов сделайте один раз в Setup-е. Дальше им пользуйтесь.

2.Конвертацию проще задать для всех пяти -

      ds.reset();        
      ds.write(0xCC);      //Команда инициации
      ds.write(0x44);      //Команда на конвертирование

Это строки с 110 по 116. В 116 единичка была нужна для паразитного питания. Эту функцию вызываете один раз и через 750мС можете со всех датчиков взять температуру.

3. Массив из функции вернется сам, если задать его как глобальную переменную.

Упростите сперва код по максимуму и выкиньте все лишние действия, а потом уже гонять.

bwn
Offline
Зарегистрирован: 25.08.2014

Да и переменные, которые вы несколько раз переопределяете, выберите которые должны быть глобальными, пусть ими и будут.

Slavyanin55
Slavyanin55 аватар
Offline
Зарегистрирован: 01.06.2014

Сложно как то у тебя все... ни к чему это все. У меня 3 датчика DS18B20 и один DHT11, замеры температур происходит раз в две минуты, и все ок.

вот http://arduino.ru/forum/proekty/sistema-umnyi-dom-dlya-zagorodnogo-doma-na-arduino-mega2560-hc-05-sim900dht113-kh-ds18

bwn
Offline
Зарегистрирован: 25.08.2014

Slavyanin55 пишет:

Сложно как то у тебя все... ни к чему это все. У меня 3 датчика DS18B20 и один DHT11, замеры температур происходит раз в две минуты, и все ок.

вот http://arduino.ru/forum/proekty/sistema-umnyi-dom-dlya-zagorodnogo-doma-na-arduino-mega2560-hc-05-sim900dht113-kh-ds18

Так я и говорю, что проблема скорее всего в этом компоте.

dimontie
Offline
Зарегистрирован: 11.01.2015

Спасибо за советы.

Все по делу.

dimontie
Offline
Зарегистрирован: 11.01.2015

Новый прикол.

#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++;
  }
}

 

Выдает:
Start
Serching for DS
Addr = 28 FF 88 8 62 14 3 7E  
Addr = 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  
Setup complete
Addr = 28 FF 88 8 62 14 3 7E  
Addr = 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 = 28 FF 88 8 62 14 3 7E  
Addr = 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 = 28 FF 88 8 62 14 3 7E  
Addr = 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  
 
Однако если в поиске не выводить переменную с адресами, то она пустая:
 
#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++;
  }
}

 

 
Start
Serching for DS
Setup complete
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
Addr = 0 0 0 0 0 0 0 0  
 
 
 
dimontie
Offline
Зарегистрирован: 11.01.2015

Это явно глюк компилятора. 1.0.6

bwn
Offline
Зарегистрирован: 25.08.2014

Завтра попробую поюзать, х-ня какая то.

bwn
Offline
Зарегистрирован: 25.08.2014
dimontie
Offline
Зарегистрирован: 11.01.2015

Переделаю счетчики в циклах на byte вечером.

bwn
Offline
Зарегистрирован: 25.08.2014

dimontie пишет:

Переделаю счетчики в циклах на byte вечером.

Вы лучше сразу определитесь со всеми переменными, их типами и областями видимости. http://arduino.ru/Tutorial/Variables

Не забываем, что в процессе вычислений переменная может неявно изменить свой тип.

Более толково про это может старшие товарищи расскажут.

dimontie
Offline
Зарегистрирован: 11.01.2015

bwn пишет:

dimontie пишет:

Переделаю счетчики в циклах на byte вечером.

Вы лучше сразу определитесь со всеми переменными, их типами и областями видимости. http://arduino.ru/Tutorial/Variables

Не забываем, что в процессе вычислений переменная может неявно изменить свой тип.

Более толково про это может старшие товарищи расскажут.

Спасибо за информацию.

Можешь привести пример когда переменная может неявно изменить свой тип?

bwn
Offline
Зарегистрирован: 25.08.2014

Где то  попадалось, что пытается принять тип приближенный к типу  полученному в результате выполнения выражения. Сейчас уже не найду. Основное, когда что то идет не так, проверить принимаемые значения используемых переменных. Собака там роется весьма часто. Почему у вас колбасило переменную "а", вразумительно объяснить не могу.

bwn
Offline
Зарегистрирован: 25.08.2014

Часть проблемы нашел. Лебедев.М.Б. CodeVisionAVR "Локальные переменные - это переменные доступные только в функциях, где они объявлены. Локальные переменные при вызове функции автоматически не инициализируются и могут содержать всякий мусор."

bwn
Offline
Зарегистрирован: 25.08.2014

bwn пишет:

Где то  попадалось, что пытается принять тип приближенный к типу  полученному в результате выполнения выражения. Сейчас уже не найду. Основное, когда что то идет не так, проверить принимаемые значения используемых переменных. Собака там роется весьма часто. Почему у вас колбасило переменную "а", вразумительно объяснить не могу.

Ввел я вас немного в блуд, это происходит в скрытой от вас форме в процессе вычислений. А вот результаты этой математики могут быть весьма поразительными. Компилятор спокойно скушает byte a=90000; , а итог сами проверьте.

dimontie
Offline
Зарегистрирован: 11.01.2015

Да. Вы правы. переменная а, видимо, содержала мусор. Я задал ее явно при инициализации и все заработало как надо.

сейчас код выгладит так:

#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;
}

В сериал порту следующее:

Start
Starting DHT
Serching for DS
Setup complete
Starting measurments
wait 1000 mSec
7D 1 55 0 7F FF C 10 1  CRC=1 C=23.81
80 1 55 0 7F FF C 10 5A  CRC=5A C=24.00
84 1 55 0 7F FF C 10 4F  CRC=4F C=24.25
80 1 55 0 7F FF C 10 5A  CRC=5A C=24.00
7E 1 55 0 7F FF C 10 C4  CRC=C4 C=23.87
Measurments completed
Hum=35.00,Temp=23.00
Starting measurments
wait 1000 mSec
7D 1 55 0 7F FF C 10 1  CRC=1 C=23.81
80 1 55 0 7F FF C 10 5A  CRC=5A C=24.00
84 1 55 0 7F FF C 10 4F  CRC=4F C=24.25
80 1 55 0 7F FF C 10 5A  CRC=5A C=24.00
7E 1 55 0 7F FF C 10 C4  CRC=C4 C=23.87
Measurments completed
Hum=35.00,Temp=23.00
 
Спасибо!
Надо взять за правило, что переменные обязательно должны быть заполнены при инициализации или проверяться перед первом обращением к ней.

 

bwn
Offline
Зарегистрирован: 25.08.2014

Да это не я, а учебник AVRа. Кстати глобальные сами инициализируются 0.

А код дальше чистите, delay() повыкидывайте, строки ненужные и пр.

dimontie
Offline
Зарегистрирован: 11.01.2015

Еще прикол в подтверждение мусора при приведении типов:

строка 016 delta умножаю положительное int на положительное число и кладу в лонг. в результате delta принимает непонятное отридцательное значение.

переделал int на long.

bwn
Offline
Зарегистрирован: 25.08.2014

dimontie пишет:

Еще прикол в подтверждение мусора при приведении типов:

строка 016 delta умножаю положительное int на положительное число и кладу в лонг. в результате delta принимает непонятное отридцательное значение.

переделал int на long.

Судя по множителю, вы здесь за пределы int-а ушли, вот и поразительный результат.

dimontie
Offline
Зарегистрирован: 11.01.2015

Грабли сплошные.

Я присваиваю longу значение inta умноженного на int число. Компилятор должен увидеть, что я результат хочу положить в лонг и понять. А получается, что он просто берет int, копирует его, умножает, а уже переполненый результат пишет в лонг.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Приведите первый инт к лонгу и переполнения не будет. Где то про это уже была тема.

bwn
Offline
Зарегистрирован: 25.08.2014

dimontie пишет:

Грабли сплошные.

Я присваиваю longу значение inta умноженного на int число. Компилятор должен увидеть, что я результат хочу положить в лонг и понять. А получается, что он просто берет int, копирует его, умножает, а уже переполненый результат пишет в лонг.

Для него в данном случае приоритет стоит на правую часть. Он и работает с int-ами, как умеет. Если бы один из множителей был long-ом и получаемое значение long или float, проблемы бы тоже не было. Значит сразу прикидывать какой диапазон может принять значение и под него назначать тип переменных.

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

bwn
Offline
Зарегистрирован: 25.08.2014

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

Прямо Фрейд какой-то))))

 

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

Вас почитаешь, так прям страшно становится :) Компилятор не один проход делает, выделить память правильного размера под переменную, это для него одна из первых задач. А вот бездумное использование буферов последовательного порта - проблема программера. Мне вот просто интересно, вы когда в последовательный порт данными кидаетесь, вы себе что представляете... ну как эти данные обрабатываются, куда складываются, как и как быстро отправляются ? Может вам руководство почитать да и увеличить размер буфера отправки последовательного порта, или скорость например ?

bwn
Offline
Зарегистрирован: 25.08.2014

brokly пишет:

Вас почитаешь, так прям страшно становится :) Компилятор не один проход делает, выделить память правильного размера под переменную, это для него одна из первых задач. А вот бездумное использование буферов последовательного порта - проблема программера. Мне вот просто интересно, вы когда в последовательный порт данными кидаетесь, вы себе что представляете... ну как эти данные обрабатываются, куда складываются, как и как быстро отправляются ? Может вам руководство почитать да и увеличить размер буфера отправки последовательного порта, или скорость например ?

Ну так основная масса здесь и собралась, чтобы понять эти процессы. Я попытался объяснить как сам понимаю эту проблему, т.к. больше никто не берется. Только когда я учился, кибернетика еще была продажной девкой империализма, а програмирование логарифмической линейкой. И если вы зная больше, возьмете на себя труд объяснить эти механизмы, доходчиво для дилетантов, то все будут только благодарны. Основной массе присутствующих академические знания не нужны. Достаточно знать, что делать нельзя и почему. Раньше это хорошо делал leshak, но куда то исчез. (((

dimontie
Offline
Зарегистрирован: 11.01.2015

Я представляю себя руководителем предприятия (ну или королем небольшой страны) и пользуясь своими полномочиями, издаю приказы (типа Serial.print (советники - IDE подкрашивает)), и кидаюсь распоряжениями)). Народ, вывести в порт "бла, бла, бла"! Если приказ непосилен для народа, то советники перед передачей исполнителям должны сообщить мне об этом. Если дума - советники пропустили (разноцветный приказ), то значит инструкции ассемблера (служащие) должны заставить народ выполнить!

Буферы портов (планирую использовать 3 порта) - это грядущие грабли. планирую подключить sim900 и оба по серийным портам))

Видимо, придется вести себя как сапер, а не как король((

dimontie
Offline
Зарегистрирован: 11.01.2015

Я король! Почему мне приходится вникать из чего сделаны шахматы?))))))

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

Ну я то же не молод :) У меня уже сынок институт закончил. Попробую разжевать. Скорость отправки одного байта по последовательному интерфейсу конечна. Если 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   могут дать различные результаты.

Я же говорю, достаточно чего нибудь почитать :)    

 

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

Может потому, что король голый ? У королей над ардуиной нет советников, есть только народ.

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

 

dimontie
Offline
Зарегистрирован: 11.01.2015

Ну вообще круто!

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

Придется читать мунускрипты. Зато это можно делать и в короне, хоть и голышом))

Datak
Offline
Зарегистрирован: 09.10.2014

brokly пишет:
Кстати, при нормальном объявлении переменной компилятор обнуляет выделенную область, иными словами: 

int a    и    int a = 0   два идентичных объявление переменной. Непроинициализированной переменная может оказаться только если вы объявите указатель на нее, а потом попробуете ее протитать по этому указателю.

Не вводите народ в заблуждение! :)
Совершенно правильно кто-то выше писал - инициализируются глобальные переменные, а локальные - нет.

Не совсем уверен насчёт статических локальных. Кажется, они тоже инициализируются нулями.

brokly пишет:
При неявных преобразованиях типов компилятор ведет себя не предсказуемо, иными словами:

long r;

int a,b;

r=a+b    и    r=(long)a + (long)b   могут дать различные результаты.

На самом деле, вполне предсказуемо, и правила там достаточно чёткие... но обычно их никто не помнит. :)
Поэтому, да, в сомнительных случаях лучше указывать тип операндов явно.

brokly пишет:
...програмная будет таймингами дергать ногу пока байт не передастся полностью, поэтому во втором случае буфера просто нет :)

Опять же, так можно говорить только про какую-то конкретную программную реализацию.
В другой реализации разработчик вполне может организовать такой же буфер для данных, и такую же "фоновую" передачу по прерываниям. Кстати, по-хорошему, так оно и должно делаться.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

brokly пишет:

r=a+b    и    r=(long)a + (long)b   могут дать различные результаты.

Вполне достаточно написать:

r=(long)a + b

 

Datak
Offline
Зарегистрирован: 09.10.2014

Насчёт сложений/умножений правила примерно такие:

Операнды приводятся к одному типу. Выбирается тип операнда, дающий большую точность, но при этом не меньше чем int.

Результат операции будет иметь такой же тип.

Операция присваивания - это следующая, отдельная операция, со своими правилами. Там компилятор уже готовый результат приводит к нужному типу.

 

Это так, по памяти, могу немного ошибаться. Если что - прошу поправить.

 

dimontie
Offline
Зарегистрирован: 11.01.2015

Вообще, заработало именно когда, присвоил значение переменной перед обрещении к ней. И когда она была int и когда стала byte.

Я выводил переменную "а" в серийный порт и ее значения были корректны 0,1,2,3,4 и при этом все работало как надо. Не работало только когда я не выводил "а" в серийный порт.

Пробовал просто ерунду выводить в порт (не работает). Работает только когда вывожу "а" в порт, или задаю ее до первого обращения к ней. До вывода в порт "а" принимает значение, которое знает только микроконтроллер))).

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

Вы два примера покажите. А так по "голословию" я могу мульон предположений сделать почему, да отчего.

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

Datak пишет:

Не вводите народ в заблуждение! :)

Совершенно правильно кто-то выше писал - инициализируются глобальные переменные, а локальные - нет.

Не совсем уверен насчёт статических локальных. Кажется, они тоже инициализируются нулями.

"Где ж ты раньше был, целовался с кем ?" Это общепринятые правила СИ. Компилятор задействованый под ардуино иногда поступает по своему :) Копались в полученых, после компилляции кодах ? Рекомендую :)

Datak пишет:

Опять же, так можно говорить только про какую-то конкретную программную реализацию.

В другой реализации разработчик вполне может организовать такой же буфер для данных, и такую же "фоновую" передачу по прерываниям. Кстати, по-хорошему, так оно и должно делаться.

Разумнее было бы, то что вы написали обзывать програмно-аппаратной реализацией, к тому же она ближе к аппаратной, будьте вдумчевее, не пытайтесь поймать меня "за язык" :)

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

kisoft пишет:

[Вполне достаточно написать:

r=(long)a + b

Полностью согласен.

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

Datak пишет:

Насчёт сложений/умножений правила примерно такие:

Операнды приводятся к одному типу. Выбирается тип операнда, дающий большую точность, но при этом не меньше чем int.

Результат операции будет иметь такой же тип.

Операция присваивания - это следующая, отдельная операция, со своими правилами. Там компилятор уже готовый результат приводит к нужному типу.

 

Это так, по памяти, могу немного ошибаться. Если что - прошу поправить.

 

Не вводите людей в заблуждение.

int a,

byte b=255;

byte c=255;

a = c + b;

У вас получится 510 ? Сильно сомневаюсь :)

a=(int)b+c, уверен будет 510.

bwn
Offline
Зарегистрирован: 25.08.2014

brokly пишет:

Datak пишет:

Насчёт сложений/умножений правила примерно такие:

Операнды приводятся к одному типу. Выбирается тип операнда, дающий большую точность, но при этом не меньше чем 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);
}

 

bwn
Offline
Зарегистрирован: 25.08.2014

С умножением такой номер не проходит.

Погорячился, со значениями в и с =181, халява проходит. И полность проходит если a - unsigned int.