Миниатюрный комнатный термометр на Attiny85 c OLED

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Просто маленький термометр/барометр/гигрометр на BME280 и Attiny85

Питается от батареек CR2032, в спящем режиме потребление 7 мкА, в режиме отображения <10мА

Отображение включается кнопкой, и поочередно сменяются значения в течении 38 секунд

 

001#include <TinyOzOLED.h>
002#include <TinyWireM.h>
003#include <avr/sleep.h>
004#define BME280_ADDRESS 0x76
005unsigned long int hum_raw, temp_raw, pres_raw;
006signed long int t_fine;
007 
008uint16_t dig_T1;
009int16_t dig_T2;
010int16_t dig_T3;
011uint16_t dig_P1;
012int16_t dig_P2;
013int16_t dig_P3;
014int16_t dig_P4;
015int16_t dig_P5;
016int16_t dig_P6;
017int16_t dig_P7;
018int16_t dig_P8;
019int16_t dig_P9;
020int8_t  dig_H1;
021int16_t dig_H2;
022int8_t  dig_H3;
023int16_t dig_H4;
024int16_t dig_H5;
025int8_t  dig_H6;
026 
027#ifndef cbi
028#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
029#endif
030#ifndef sbi
031#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
032#endif
033 
034// PB0 pin 5 - SDA
035#define PB0_OUT sbi(DDRB,PB0)
036#define PB0_IN cbi(DDRB,PB0)
037#define PB0_HIGH sbi(PORTB,PB0)
038#define PB0_LOW cbi(PORTB,PB0)
039// PB1 pin 6
040#define PB1_OUT sbi(DDRB,PB1)
041#define PB1_IN cbi(DDRB,PB1)
042#define PB1_HIGH sbi(PORTB,PB1)
043#define PB1_LOW cbi(PORTB,PB1)
044// PB2 pin 7 - SCL
045#define PB2_OUT sbi(DDRB,PB2)
046#define PB2_IN cbi(DDRB,PB2)
047#define PB2_HIGH sbi(PORTB,PB2)
048#define PB2_LOW cbi(PORTB,PB2)
049// PB3 pin 2 - WakeUp KEY
050#define PB3_OUT sbi(DDRB,PB3)
051#define PB3_IN cbi(DDRB,PB3)
052#define PB3_HIGH sbi(PORTB,PB3)
053#define PB3_LOW cbi(PORTB,PB3)
054#define PB3_READ bitRead(PINB,PB3)
055// PB4 pin 3
056#define PB4_OUT sbi(DDRB,PB4)
057#define PB4_IN cbi(DDRB,PB4)
058#define PB4_HIGH sbi(PORTB,PB4)
059#define PB4_LOW cbi(PORTB,PB4)
060 
061boolean firstStart;
062unsigned long showTimer;
063unsigned long wakeUpTimer;
064byte showMode; // 0-temp 1-pres 2-hum
065boolean changeMode;
066 
067void writeReg(uint8_t reg_address, uint8_t data) {
068  TinyWireM.beginTransmission(BME280_ADDRESS);
069  TinyWireM.write(reg_address);
070  TinyWireM.write(data);
071  TinyWireM.endTransmission();
072}
073 
074void initBME280() {
075  TinyWireM.begin();
076 
077  uint8_t osrs_t = 1;             //Temperature oversampling x 1
078  uint8_t osrs_p = 1;             //Pressure oversampling x 1
079  uint8_t osrs_h = 2;             //Humidity oversampling x 1
080  uint8_t mode = 3;               //Normal mode
081  uint8_t t_sb = 5;               //Tstandby 1000ms
082  uint8_t filter = 0;             //Filter off
083  uint8_t spi3w_en = 0;           //3-wire SPI Disable
084 
085  uint8_t ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
086  uint8_t config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en;
087  uint8_t ctrl_hum_reg  = osrs_h;
088  writeReg(0xF2, ctrl_hum_reg);
089  writeReg(0xF4, ctrl_meas_reg);
090  writeReg(0xF5, config_reg);
091  readTrim();
092}
093 
094void resetBME280() {
095  writeReg(0xE0, 0xB6);
096}
097 
098signed long int calibration_T(signed long int adc_T)
099{
100 
101  signed long int var1, var2, T;
102  var1 = ((((adc_T >> 3) - ((signed long int)dig_T1 << 1))) * ((signed long int)dig_T2)) >> 11;
103  var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T >> 4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;
104 
105  t_fine = var1 + var2;
106  T = (t_fine * 5 + 128) >> 8;
107  return T;
108}
109 
110void readTrim()  {
111  uint8_t data[32], i = 0;
112  TinyWireM.beginTransmission(BME280_ADDRESS);
113  TinyWireM.write(0x88);
114  TinyWireM.endTransmission();
115  TinyWireM.requestFrom(BME280_ADDRESS, 24);
116  while (TinyWireM.available()) {
117    data[i] = TinyWireM.read();
118    i++;
119  }
120 
121  TinyWireM.beginTransmission(BME280_ADDRESS);
122  TinyWireM.write(0xA1);
123  TinyWireM.endTransmission();
124  TinyWireM.requestFrom(BME280_ADDRESS, 1);
125  data[i] = TinyWireM.read();
126  i++;
127 
128  TinyWireM.beginTransmission(BME280_ADDRESS);
129  TinyWireM.write(0xE1);
130  TinyWireM.endTransmission();
131  TinyWireM.requestFrom(BME280_ADDRESS, 7);
132  while (TinyWireM.available()) {
133    data[i] = TinyWireM.read();
134    i++;
135  }
136  dig_T1 = (data[1] << 8) | data[0];
137  dig_T2 = (data[3] << 8) | data[2];
138  dig_T3 = (data[5] << 8) | data[4];
139  dig_P1 = (data[7] << 8) | data[6];
140  dig_P2 = (data[9] << 8) | data[8];
141  dig_P3 = (data[11] << 8) | data[10];
142  dig_P4 = (data[13] << 8) | data[12];
143  dig_P5 = (data[15] << 8) | data[14];
144  dig_P6 = (data[17] << 8) | data[16];
145  dig_P7 = (data[19] << 8) | data[18];
146  dig_P8 = (data[21] << 8) | data[20];
147  dig_P9 = (data[23] << 8) | data[22];
148  dig_H1 = data[24];
149  dig_H2 = (data[26] << 8) | data[25];
150  dig_H3 = data[27];
151  dig_H4 = (data[28] << 4) | (0x0F & data[29]);
152  dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
153  dig_H6 = data[31];
154}
155 
156ISR(PCINT0_vect) {
157  if (PB3_READ == 0) { // LOW level KEY
158    sleep_disable();
159    cbi(GIMSK, PCIE);
160    cbi(PCMSK, PCINT3);
161  }
162}
163 
164void toSleep() {
165  // pins mode
166  PB0_IN; PB0_LOW;
167  PB1_OUT; PB1_LOW;
168  PB2_IN; PB2_LOW;
169  PB3_IN; PB3_HIGH; // LOW = OFF res, if HIGH level KEY
170  PB4_OUT; PB4_LOW;
171  // sleep
172  cbi(ADCSRA, ADEN);
173  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
174  sleep_enable();
175  sbi(GIMSK, PCIE);
176  sbi(PCMSK, PCINT3);
177  sleep_mode();
178}
179 
180void setup () {
181  firstStart = true;
182}
183 
184void readData()
185{
186  int i = 0;
187  uint32_t data[8];
188  TinyWireM.beginTransmission(BME280_ADDRESS);
189  TinyWireM.write(0xF7);
190  TinyWireM.endTransmission();
191  TinyWireM.requestFrom(BME280_ADDRESS, 8);
192  while (TinyWireM.available()) {
193    data[i] = TinyWireM.read();
194    i++;
195  }
196  pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
197  temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
198  hum_raw  = (data[6] << 8) | data[7];
199  temp_raw = calibration_T(temp_raw);
200  pres_raw = (calibration_P(pres_raw) / 133.32) - 5;
201  hum_raw = calibration_H(hum_raw) / 1024;
202}
203 
204void loop () {
205  unsigned long curr_millis = millis();
206  if (firstStart) {
207    toSleep();
208    firstStart = false;
209    wakeUpTimer = curr_millis;
210    showMode = 0;
211    showTimer = curr_millis;
212    changeMode = true;
213    // get data from BME280
214    initBME280();
215    readData();
216    resetBME280();
217    OzOled.init();  //инициализация дисплей
218    OzOled.setNormalDisplay();      //нормальный режим
219    OzOled.setPageMode();           //адресация страничная
220    OzOled.sendCommand(0xA1);       //выбор ориентации сверху - вниз
221    OzOled.sendCommand(0xC8);       //слева - направо
222  }
223  // work
224  if ((curr_millis - showTimer) >= 4000UL) { // change disp every 4 sec
225    showTimer = curr_millis;
226    changeMode = true;
227    ++showMode;
228    if (showMode > 2) {
229      showMode = 0;
230    }
231  }
232  if (changeMode) {
233    OzOled.clearDisplay();          //очистка дисплея
234    switch (showMode) {
235      case 1: {
236          char str[4] = "";
237          str[0] = (pres_raw / 100) + 0x30;
238          str[1] = (pres_raw % 100) / 10 + 0x30;
239          str[2] = (pres_raw % 100) % 10 + 0x30;
240          str[3] = 0x00;
241          OzOled.printBigNumber(str, 3, 0);
242          break;
243        }
244      case 2: {
245          /*char str[6] = "";
246            str[0] = (hum_raw / 10000) + 0x30;
247            str[1] = (hum_raw % 10000)/1000 + 0x30;
248            str[2] = ((hum_raw % 10000)%1000)/100 + 0x30;
249            str[3] = (((hum_raw % 10000)%1000)%100)/10 + 0x30;
250            str[4] = (((hum_raw % 10000)%1000)%100)%10 + 0x30;
251            str[5] = 0x00;*/
252          char str[3] = "";
253          str[0] = hum_raw / 10 + 0x30;
254          str[1] = hum_raw % 10 + 0x30;
255          str[2] = 0x00;
256          OzOled.printBigNumber(str, 6, 0);
257          break;
258        }
259      default: { // show temp
260          char str[6] = "";
261          str[0] = (temp_raw / 1000) + 0x30;
262          str[1] = (temp_raw % 1000) / 100 + 0x30;
263          str[2] = '.';
264          str[3] = ((temp_raw % 1000) % 100) / 10 + 0x30;
265          str[4] = ((temp_raw % 1000) % 100) % 10 + 0x30;
266          str[5] = 0x00;
267          OzOled.printBigNumber(str, 0, 0);
268        }
269    }
270    changeMode = false;
271  }
272  // OFF show data
273  if ((curr_millis - wakeUpTimer) >= 39000UL) { // show 39 sec
274    firstStart = true;
275    // OFF display
276    OzOled.setPowerOff();
277    // OFF BME
278  }
279}
280 
281unsigned long int calibration_P(signed long int adc_P)  {
282  signed long int var1, var2;
283  unsigned long int P;
284  var1 = (((signed long int)t_fine) >> 1) - (signed long int)64000;
285  var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * ((signed long int)dig_P6);
286  var2 = var2 + ((var1 * ((signed long int)dig_P5)) << 1);
287  var2 = (var2 >> 2) + (((signed long int)dig_P4) << 16);
288  var1 = (((dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((((signed long int)dig_P2) * var1) >> 1)) >> 18;
289  var1 = ((((32768 + var1)) * ((signed long int)dig_P1)) >> 15);
290  if (var1 == 0)
291  {
292    return 0;
293  }
294  P = (((unsigned long int)(((signed long int)1048576) - adc_P) - (var2 >> 12))) * 3125;
295  if (P < 0x80000000)
296  {
297    P = (P << 1) / ((unsigned long int) var1);
298  }
299  else
300  {
301    P = (P / (unsigned long int)var1) * 2;
302  }
303  var1 = (((signed long int)dig_P9) * ((signed long int)(((P >> 3) * (P >> 3)) >> 13))) >> 12;
304  var2 = (((signed long int)(P >> 2)) * ((signed long int)dig_P8)) >> 13;
305  P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
306  return P;
307}
308 
309unsigned long int calibration_H(signed long int adc_H)  {
310  signed long int v_x1;
311 
312  v_x1 = (t_fine - ((signed long int)76800));
313  v_x1 = (((((adc_H << 14) - (((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) +
314            ((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) *
315                (((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) *
316                ((signed long int) dig_H2) + 8192) >> 14));
317  v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
318  v_x1 = (v_x1 < 0 ? 0 : v_x1);
319  v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
320  return (unsigned long int)(v_x1 >> 12);
321}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Классный проект, нужный. У мня такой жэ, маленько проще, на 27 строчек кода. И тока мой на улице валяеца.  С баторейкой на 9 Вольт.  И жена пилит, когда я буквы побольше сделаю. А мне лень. :) 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

дома тупо термометра и барометра нет - вот и собрал из того что было, осталось в спичесный коробок засунуть

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

поторопился я выкладывать :( - нашел серъезную ошибку, исправленый текст ниже.

влажность показывает странную - 33...34% но мне она не нужна , потому не разбирался.

также с моим OLED дисплеем из Китая не заработала стандартная библиотека TinyOzOLED - пришлось ее корректировать - если кого заинтересует - выложу.

001#include <TinyOzOLED.h>
002#include <TinyWireM.h>
003#include <avr/sleep.h>
004#define BME280_ADDRESS 0x76
005unsigned long int hum_raw, temp_raw, pres_raw;
006signed long int t_fine;
007 
008uint16_t dig_T1;
009int16_t dig_T2;
010int16_t dig_T3;
011uint16_t dig_P1;
012int16_t dig_P2;
013int16_t dig_P3;
014int16_t dig_P4;
015int16_t dig_P5;
016int16_t dig_P6;
017int16_t dig_P7;
018int16_t dig_P8;
019int16_t dig_P9;
020int8_t  dig_H1;
021int16_t dig_H2;
022int8_t  dig_H3;
023int16_t dig_H4;
024int16_t dig_H5;
025int8_t  dig_H6;
026 
027#ifndef cbi
028#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
029#endif
030#ifndef sbi
031#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
032#endif
033 
034// PB0 pin 5 - SDA
035#define PB0_OUT sbi(DDRB,PB0)
036#define PB0_IN cbi(DDRB,PB0)
037#define PB0_HIGH sbi(PORTB,PB0)
038#define PB0_LOW cbi(PORTB,PB0)
039// PB1 pin 6
040#define PB1_OUT sbi(DDRB,PB1)
041#define PB1_IN cbi(DDRB,PB1)
042#define PB1_HIGH sbi(PORTB,PB1)
043#define PB1_LOW cbi(PORTB,PB1)
044// PB2 pin 7 - SCL
045#define PB2_OUT sbi(DDRB,PB2)
046#define PB2_IN cbi(DDRB,PB2)
047#define PB2_HIGH sbi(PORTB,PB2)
048#define PB2_LOW cbi(PORTB,PB2)
049// PB3 pin 2 - WakeUp KEY
050#define PB3_OUT sbi(DDRB,PB3)
051#define PB3_IN cbi(DDRB,PB3)
052#define PB3_HIGH sbi(PORTB,PB3)
053#define PB3_LOW cbi(PORTB,PB3)
054#define PB3_READ bitRead(PINB,PB3)
055// PB4 pin 3
056#define PB4_OUT sbi(DDRB,PB4)
057#define PB4_IN cbi(DDRB,PB4)
058#define PB4_HIGH sbi(PORTB,PB4)
059#define PB4_LOW cbi(PORTB,PB4)
060 
061boolean firstStart;
062unsigned long showTimer;
063unsigned long wakeUpTimer;
064byte showMode; // 0-temp 1-pres 2-hum
065boolean changeMode;
066 
067void writeReg(uint8_t reg_address, uint8_t data) {
068  TinyWireM.beginTransmission(BME280_ADDRESS);
069  TinyWireM.write(reg_address);
070  TinyWireM.write(data);
071  TinyWireM.endTransmission();
072}
073 
074void initBME280() {
075 
076  uint8_t osrs_t = 1;             //Temperature oversampling x 1
077  uint8_t osrs_p = 1;             //Pressure oversampling x 1
078  uint8_t osrs_h = 2;             //Humidity oversampling x 1
079  uint8_t mode = 3;               //Normal mode
080  uint8_t t_sb = 5;               //Tstandby 1000ms
081  uint8_t filter = 0;             //Filter off
082  uint8_t spi3w_en = 0;           //3-wire SPI Disable
083 
084  uint8_t ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
085  uint8_t config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en;
086  uint8_t ctrl_hum_reg  = osrs_h;
087  writeReg(0xF2, ctrl_hum_reg);
088  writeReg(0xF4, ctrl_meas_reg);
089  writeReg(0xF5, config_reg);
090  readTrim();
091}
092 
093ISR(PCINT0_vect) {
094  if (PB3_READ == 0) { // LOW level KEY
095    sleep_disable();
096    cbi(GIMSK, PCIE);
097    cbi(PCMSK, PCINT3);
098  }
099}
100 
101void toSleep() {
102  // pins mode
103  PB0_IN; PB0_LOW;
104  PB1_OUT; PB1_LOW;
105  PB2_IN; PB2_LOW;
106  PB3_IN; PB3_HIGH; // LOW = OFF res, if HIGH level KEY
107  PB4_OUT; PB4_LOW;
108  // sleep
109  cbi(ADCSRA, ADEN);
110  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
111  sleep_enable();
112  sbi(GIMSK, PCIE);
113  sbi(PCMSK, PCINT3);
114  sleep_mode();
115}
116 
117void setup () {
118  firstStart = true;
119  TinyWireM.begin();
120  initBME280();
121}
122 
123void readData()
124{
125  int i = 0;
126  uint32_t data[8];
127  TinyWireM.beginTransmission(BME280_ADDRESS);
128  TinyWireM.write(0xF7);
129  TinyWireM.endTransmission();
130  TinyWireM.requestFrom(BME280_ADDRESS, 8);
131  while (TinyWireM.available()) {
132    data[i] = TinyWireM.read();
133    i++;
134  }
135  pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
136  temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
137  hum_raw  = (data[6] << 8) | data[7];
138  temp_raw = calibration_T(temp_raw);
139  pres_raw = (calibration_P(pres_raw) / 133.32) - 5;
140  hum_raw = calibration_H(hum_raw) / 1024;
141}
142 
143void loop () {
144  unsigned long curr_millis = millis();
145  if (firstStart) {
146    toSleep();
147    firstStart = false;
148    wakeUpTimer = curr_millis;
149    showMode = 0;
150    showTimer = curr_millis;
151    changeMode = true;
152    // get data from BME280
153    TinyWireM.begin();
154    t_fine = 0;
155    readData();
156    OzOled.init();  //инициализация дисплей
157    OzOled.setNormalDisplay();      //нормальный режим
158    OzOled.setPageMode();           //адресация страничная
159    OzOled.sendCommand(0xA1);       //выбор ориентации сверху - вниз
160    OzOled.sendCommand(0xC8);       //слева - направо
161  }
162  // work
163  if ((curr_millis - showTimer) >= 4000UL) { // change disp every 4 sec
164    showTimer = curr_millis;
165    changeMode = true;
166    ++showMode;
167    if (showMode > 2) {
168      showMode = 0;
169    }
170  }
171  if (changeMode) {
172    OzOled.clearDisplay();          //очистка дисплея
173    switch (showMode) {
174      case 1: {
175          char str[4] = "";
176          str[0] = (pres_raw / 100) + 0x30;
177          str[1] = (pres_raw % 100) / 10 + 0x30;
178          str[2] = (pres_raw % 100) % 10 + 0x30;
179          str[3] = 0x00;
180          OzOled.printBigNumber(str, 3, 0);
181          break;
182        }
183      case 2: {
184          char str[3] = "";
185          str[0] = hum_raw / 10 + 0x30;
186          str[1] = hum_raw % 10 + 0x30;
187          str[2] = 0x00;
188          OzOled.printBigNumber(str, 6, 0);
189          break;
190        }
191      default: { // show temp
192          char str[6] = "";
193          str[0] = (temp_raw / 1000) + 0x30;
194          str[1] = (temp_raw % 1000) / 100 + 0x30;
195          str[2] = '.';
196          str[3] = ((temp_raw % 1000) % 100) / 10 + 0x30;
197          str[4] = ((temp_raw % 1000) % 100) % 10 + 0x30;
198          str[5] = 0x00;
199          OzOled.printBigNumber(str, 0, 0);
200        }
201    }
202    changeMode = false;
203  }
204  // OFF show data
205  if ((curr_millis - wakeUpTimer) >= 40000UL) {
206    firstStart = true;
207    // OFF display
208    OzOled.setPowerOff();
209  }
210}
211 
212unsigned long int calibration_P(signed long int adc_P)  {
213  signed long int var1, var2;
214  unsigned long int P;
215  var1 = (((signed long int)t_fine) >> 1) - (signed long int)64000;
216  var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * ((signed long int)dig_P6);
217  var2 = var2 + ((var1 * ((signed long int)dig_P5)) << 1);
218  var2 = (var2 >> 2) + (((signed long int)dig_P4) << 16);
219  var1 = (((dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((((signed long int)dig_P2) * var1) >> 1)) >> 18;
220  var1 = ((((32768 + var1)) * ((signed long int)dig_P1)) >> 15);
221  if (var1 == 0)
222  {
223    return 0;
224  }
225  P = (((unsigned long int)(((signed long int)1048576) - adc_P) - (var2 >> 12))) * 3125;
226  if (P < 0x80000000)
227  {
228    P = (P << 1) / ((unsigned long int) var1);
229  }
230  else
231  {
232    P = (P / (unsigned long int)var1) * 2;
233  }
234  var1 = (((signed long int)dig_P9) * ((signed long int)(((P >> 3) * (P >> 3)) >> 13))) >> 12;
235  var2 = (((signed long int)(P >> 2)) * ((signed long int)dig_P8)) >> 13;
236  P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
237  return P;
238}
239 
240unsigned long int calibration_H(signed long int adc_H)  {
241  signed long int v_x1;
242 
243  v_x1 = (t_fine - ((signed long int)76800));
244  v_x1 = (((((adc_H << 14) - (((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) +
245            ((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) *
246                (((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) *
247                ((signed long int) dig_H2) + 8192) >> 14));
248  v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
249  v_x1 = (v_x1 < 0 ? 0 : v_x1);
250  v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
251  return (unsigned long int)(v_x1 >> 12);
252}
253 
254void resetBME280() {
255  writeReg(0xE0, 0xB6);
256}
257 
258signed long int calibration_T(signed long int adc_T)
259{
260 
261  signed long int var1, var2, T;
262  var1 = ((((adc_T >> 3) - ((signed long int)dig_T1 << 1))) * ((signed long int)dig_T2)) >> 11;
263  var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T >> 4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;
264 
265  t_fine = var1 + var2;
266  T = (t_fine * 5 + 128) >> 8;
267  return T;
268}
269 
270void readTrim()  {
271  uint8_t data[32], i = 0;
272  TinyWireM.beginTransmission(BME280_ADDRESS);
273  TinyWireM.write(0x88);
274  TinyWireM.endTransmission();
275  TinyWireM.requestFrom(BME280_ADDRESS, 24);
276  while (TinyWireM.available()) {
277    data[i] = TinyWireM.read();
278    i++;
279  }
280 
281  TinyWireM.beginTransmission(BME280_ADDRESS);
282  TinyWireM.write(0xA1);
283  TinyWireM.endTransmission();
284  TinyWireM.requestFrom(BME280_ADDRESS, 1);
285  data[i] = TinyWireM.read();
286  i++;
287 
288  TinyWireM.beginTransmission(BME280_ADDRESS);
289  TinyWireM.write(0xE1);
290  TinyWireM.endTransmission();
291  TinyWireM.requestFrom(BME280_ADDRESS, 7);
292  while (TinyWireM.available()) {
293    data[i] = TinyWireM.read();
294    i++;
295  }
296  dig_T1 = (data[1] << 8) | data[0];
297  dig_T2 = (data[3] << 8) | data[2];
298  dig_T3 = (data[5] << 8) | data[4];
299  dig_P1 = (data[7] << 8) | data[6];
300  dig_P2 = (data[9] << 8) | data[8];
301  dig_P3 = (data[11] << 8) | data[10];
302  dig_P4 = (data[13] << 8) | data[12];
303  dig_P5 = (data[15] << 8) | data[14];
304  dig_P6 = (data[17] << 8) | data[16];
305  dig_P7 = (data[19] << 8) | data[18];
306  dig_P8 = (data[21] << 8) | data[20];
307  dig_P9 = (data[23] << 8) | data[22];
308  dig_H1 = data[24];
309  dig_H2 = (data[26] << 8) | data[25];
310  dig_H3 = data[27];
311  dig_H4 = (data[28] << 4) | (0x0F & data[29]);
312  dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
313  dig_H6 = data[31];
314}

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Надо попробовать повторить :) а какую плату вы выбираете в иде?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ATtiny85 @ 1 MHz  (internal oscillator; BOD disabled)

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Понятно ... что-то с библиотеками ... буду разбираться

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ulis пишет:

Понятно ... что-то с библиотеками ... буду разбираться

в смысле? там все просто - распаковывайте архив с tiny библиотеками в hardware и все, поищите поиском Arduino as ISP для ATtiny

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Микроконтроллер я уже установил, ругается на бибилиотеку для барометра, возможно я не самую свежую скачал

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ulis пишет:

Микроконтроллер я уже установил, ругается на бибилиотеку для барометра, возможно я не самую свежую скачал

Текст ошибки чтоль показали бы....

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011
1Да ошибка понятна ...
2Clock_andycat:277: error: 'class USI_TWI' has no member named 'read'
3 
4     data[i] = TinyWireM.read();
5                         ^
6Clock_andycat:282: error: 'class USI_TWI' has no member named 'write'
7 
8   TinyWireM.write(0xA1);

 

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ulis пишет:

1Да ошибка понятна ...
2Clock_andycat:277: error: 'class USI_TWI' has no member named 'read'
3 
4     data[i] = TinyWireM.read();
5                         ^
6Clock_andycat:282: error: 'class USI_TWI' has no member named 'write'
7 
8   TinyWireM.write(0xA1);

 

 

это ошибка библиотеки барометра? вы собираетесь барометр BME280 из библиотеки использовать? не хочу вас расстраивать - ничего не получиться - памяти МК не хватит - только напрямую командами - на ГитХабе масса примеров, мой скетч в основном отттуда.

ЗЫ. хотел добавить мелкий текст - тпа градусов цельсия или мм рт столба - не влезло, сейчас занимает 94 % памяти контроллера.

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ulis пишет:

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

не понял вопроса, так и компилировал - в ардуино ИДЕ выбрал меню загрузить через программатор - он загрузил в Attiny85

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Если при компиляции возникают ошибки, как же можно загрузить в мк?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ulis пишет:

Если при компиляции возникают ошибки, как же можно загрузить в мк?

у меня не было ошибок :)

итак по пунктам:

1 скачиваете с гитраб библиотеку Tinywirem - устанавливаете

2. аналогично TinyOzOled

3. выбираете плату Attiny85

все должно скомпилироваться, если нет - как то не правильно все поставили

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

Все, обновил бибилиотеку, скомпилировалось без ошибок .... 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

91% программная память

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ulis пишет:

91% программная память

у меня TinyOzOled библиотека исправлена, потому и размер другой, если с вашим дисплеем (128*32) будет аналогичная проблема как у меня (знаки сплюснуты были) - тогда скину исправленную.

 

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

а у меня нет схемы :)

и с стоках 034..058 все же написано, там тупо три контакта МК только использовано

ulis
ulis аватар
Offline
Зарегистрирован: 09.03.2011

я так и думал ... :) ладно, нарисую сам

Zakhnnm
Offline
Зарегистрирован: 10.02.2016

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

Не подскажете, как полусенные Вами измерения отправить на RF передатчик 433Мгц ?

Для экономии памяти тиньки можно было бы отправить *_raw данные, а на стороне приемника их уже причесать.

Спасибо!

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017
Zakhnnm
Offline
Зарегистрирован: 10.02.2016

Спасибо огромное!

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
01#include <DigisparkOLED.h>
02#include <Wire.h>
03 
04 
05 
06void setup() {
07oled.begin();
08oled.clear();
09oled.setCursor(0, 0);
10oled.setFont(FONT8X16);
11oled.print(F("Hello, world!"));
12}
13 
14void loop() {
15 
16 
17}
Скетч использует 3950 байт (65%) памяти устройства. Всего доступно 6012 байт.
Глобальные переменные используют 51 байт динамической памяти.
 
Есть другие рабочие библиотеки?
asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Irinka пишет:

 
Есть другие рабочие библиотеки?

 

http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-displeya-128kh64-s-kirillitsei-utf-8

Не?

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

asam пишет:

Irinka пишет:

 
Есть другие рабочие библиотеки?

 

http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-displeya-128kh64-s-kirillitsei-utf-8

Не?

Куча ошибок при загрузке в 85

Не Digispark

makks
Offline
Зарегистрирован: 19.09.2021

andycat пишет:

у меня TinyOzOled библиотека исправлена,  если с вашим дисплеем (128*32) будет аналогичная проблема как у меня (знаки сплюснуты были) - тогда скину исправленную.

Собрал, заработало и таки да сплюснуто. Как бы получить исправленную версию библиотеки TinyOzOled?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

к сожалению не уверен что это конечная версия, проверить не на чем, файл TinyOzOLED.cpp

- исправлена одна функция

 

makks
Offline
Зарегистрирован: 19.09.2021

Спасибо. Сейчас проверю.

UPD. Да все корректно отображается. Погрел, подышал - показания с задержкой меняются адекватно. Я делал метеостанцию на BME280, 1602 и tiny85, но ваш проект более компактный, это и понравилось.

neid86@gmail.com
Offline
Зарегистрирован: 28.10.2014

Взял ваш проект переделал в Atmel Studio C++,  вроде как работает, но давление почему то плюс минул трамвайная остановка... Детально... прошил, работает и вроде как адекватные показания давление показывает. Скидываю питание опять включаю, и все... 702, скину опять может быть 735, или 768, но никак не реальные 740.  Температура и влажность чуть завышены на 1-2 градуса, влажность 1-5%. Я так понимаю это просто переписанная библиотека MyBME280.h

1) как у вас получилось 1Mhz частота МК, у вас делитель стоит на 8? У меня все завелось на 8MHz

И подскажите на что смотреть, глянул по лог.анализатору ни чего не увидел криминального... может переделать считывание калибровочных регистров 0x88...0xA1 и 0xE1...0xE7...

 

xfvlad
Offline
Зарегистрирован: 06.02.2021

Здравствуйте. Какая самая последняя идеально рабочая версия прошивки?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

xfvlad
Offline
Зарегистрирован: 06.02.2021

Тогда какой скетч использовать?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017
xfvlad
Offline
Зарегистрирован: 06.02.2021

Можете еще, пожалуйста, сбросить еще вашу библиотеку TinyOzOLED.

И обвязка есть на tiny85?

Батарейка CR2032 1 или 2 последовательно?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Библиотека на гитхабе, исправленный файл тут
http://arduino.ru/forum/proekty/miniatyurnyi-komnatnyi-termometr-na-atti...
Из обвязки только резистор 10 ком между reset и питанием, ну можно ещё конденсатор на 100...300 мкФ на питание.
Одна батарейка cr2032 или 2 параллельно, если подключите последовательно - сгорит МК и bme280.
В первом сообщении темы фото, там виден только резистор, больше ничего нет.

xfvlad
Offline
Зарегистрирован: 06.02.2021

Куда подключаются пины 3 и 6?

makks
Offline
Зарегистрирован: 19.09.2021

на пине 2 кнопка, 5 и 7 шина i2C, 4 земля и 8 плюс питания. Остальные пины свободны. можете  reset (пин1) резистором подтянуть к плюсу, у меня и без этого работает.

xfvlad
Offline
Зарегистрирован: 06.02.2021

Возможно температуру отображать с одним знаком после комы?

На символы градуса и влажности памяти не хватает?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Питание на дисплей и датчик идет постоянно ???

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

да, все загоняется в спящий режим, поэтому одной батарейки CR2032 хватает минимум на 8 месяцев

gzp13
Offline
Зарегистрирован: 06.04.2015

Пытаюсь повторить ваш проект. Не работает дисплей OLED128x32. Подключаю его к ардуине нано, закачиваю скетч SSD1306, дисплей все прекрасно отрабатывает. Подключаю к ATTINY85- экран черный. Питание есть. Может библиотека не подходит? Ядро ATTINYCORE без загрузчика.

xfvlad
Offline
Зарегистрирован: 06.02.2021

На ядре ATTINYCORE с платой в настройках ATtiny48/85 (Optiboot) все работает сейчас у меня. Прошивал через USBasp с программы

makks
Offline
Зарегистрирован: 19.09.2021

gzp13 пишет:

Подключаю к ATTINY85- экран черный. Питание есть. Может библиотека не подходит? Ядро ATTINYCORE без загрузчика.

Чем шьете Tiny?

Зашивайте хекс по ссылке - точно рабочий.

https://disk.yandex.ru/d/L6yfAyrfEfuA2w

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

gzp13 пишет:

Пытаюсь повторить ваш проект. Не работает дисплей OLED128x32. Подключаю его к ардуине нано, закачиваю скетч SSD1306, дисплей все прекрасно отрабатывает. Подключаю к ATTINY85- экран черный. Питание есть. Может библиотека не подходит? Ядро ATTINYCORE без загрузчика.


В инициализации дисплея в библиотеке есть ошибка, тут на форуме было очень давно, при включении питания дисплей не работает, при сбросе МК и соответственно повторной инициализации все взлетало :(
Что самое инересное: недавно помер от старости индикатор oled уличной температуры, заказал новый и этот косяк исчез, т е китайцы что то подкрутили.

gzp13
Offline
Зарегистрирован: 06.04.2015

Собрал,все работает) Спасибо за проект. Но вот влажность показывает нулевую. Температуру хочется выводить с одним знаком после запятой( не сообразил как это сделать).Так и должно быть, в комнате 24гр, показывает 24гр, кладу к окну,там 4гр, а этот показывает 24гр, при след.нажатии на кнопку показания уменьшаются на 0.2-0.4гр, еще раз нажимаем-еще на 0.2-0.5гр, а то и на пару сотых. По идее температура должна уменьшаться сразу, ну пусть с небольшой задержкой., но не так же, она изменяется только после нажатия кнопки и то совcем по чуть чуть.

И еще цикл индикации длится не 38сек, а каких то 5-6сек( частота 1МГц). При частоте 8МГц индикация продолжается 38сек.Но  температура не меняется пока этот цикл не завершится. Получается что этот термометр не нужен, так как он слишком инертный.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А так, да, всё работает.  :))) 

gzp13
Offline
Зарегистрирован: 06.04.2015

DetSimen пишет:

А так, да, всё работает.  :))) 

Ну работает, может и так как автор хотел. Но в моем понимании термометр хотя бы должен в течении 30сек выдать точную температуру, а он по несколько десятых изменяет и то при нажатии на кнопку.