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

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

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

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

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

 

#include <TinyOzOLED.h>
#include <TinyWireM.h>
#include <avr/sleep.h>
#define BME280_ADDRESS 0x76
unsigned long int hum_raw, temp_raw, pres_raw;
signed long int t_fine;

uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
int8_t  dig_H1;
int16_t dig_H2;
int8_t  dig_H3;
int16_t dig_H4;
int16_t dig_H5;
int8_t  dig_H6;

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// PB0 pin 5 - SDA
#define PB0_OUT sbi(DDRB,PB0)
#define PB0_IN cbi(DDRB,PB0)
#define PB0_HIGH sbi(PORTB,PB0)
#define PB0_LOW cbi(PORTB,PB0)
// PB1 pin 6
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
// PB2 pin 7 - SCL
#define PB2_OUT sbi(DDRB,PB2)
#define PB2_IN cbi(DDRB,PB2)
#define PB2_HIGH sbi(PORTB,PB2)
#define PB2_LOW cbi(PORTB,PB2)
// PB3 pin 2 - WakeUp KEY
#define PB3_OUT sbi(DDRB,PB3)
#define PB3_IN cbi(DDRB,PB3)
#define PB3_HIGH sbi(PORTB,PB3)
#define PB3_LOW cbi(PORTB,PB3)
#define PB3_READ bitRead(PINB,PB3)
// PB4 pin 3
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)

boolean firstStart;
unsigned long showTimer;
unsigned long wakeUpTimer;
byte showMode; // 0-temp 1-pres 2-hum
boolean changeMode;

void writeReg(uint8_t reg_address, uint8_t data) {
  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(reg_address);
  TinyWireM.write(data);
  TinyWireM.endTransmission();
}

void initBME280() {
  TinyWireM.begin();

  uint8_t osrs_t = 1;             //Temperature oversampling x 1
  uint8_t osrs_p = 1;             //Pressure oversampling x 1
  uint8_t osrs_h = 2;             //Humidity oversampling x 1
  uint8_t mode = 3;               //Normal mode
  uint8_t t_sb = 5;               //Tstandby 1000ms
  uint8_t filter = 0;             //Filter off
  uint8_t spi3w_en = 0;           //3-wire SPI Disable

  uint8_t ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
  uint8_t config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en;
  uint8_t ctrl_hum_reg  = osrs_h;
  writeReg(0xF2, ctrl_hum_reg);
  writeReg(0xF4, ctrl_meas_reg);
  writeReg(0xF5, config_reg);
  readTrim();
}

void resetBME280() {
  writeReg(0xE0, 0xB6);
}

signed long int calibration_T(signed long int adc_T)
{

  signed long int var1, var2, T;
  var1 = ((((adc_T >> 3) - ((signed long int)dig_T1 << 1))) * ((signed long int)dig_T2)) >> 11;
  var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T >> 4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;

  t_fine = var1 + var2;
  T = (t_fine * 5 + 128) >> 8;
  return T;
}

void readTrim()  {
  uint8_t data[32], i = 0;
  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0x88);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 24);
  while (TinyWireM.available()) {
    data[i] = TinyWireM.read();
    i++;
  }

  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0xA1);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 1);
  data[i] = TinyWireM.read();
  i++;

  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0xE1);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 7);
  while (TinyWireM.available()) {
    data[i] = TinyWireM.read();
    i++;
  }
  dig_T1 = (data[1] << 8) | data[0];
  dig_T2 = (data[3] << 8) | data[2];
  dig_T3 = (data[5] << 8) | data[4];
  dig_P1 = (data[7] << 8) | data[6];
  dig_P2 = (data[9] << 8) | data[8];
  dig_P3 = (data[11] << 8) | data[10];
  dig_P4 = (data[13] << 8) | data[12];
  dig_P5 = (data[15] << 8) | data[14];
  dig_P6 = (data[17] << 8) | data[16];
  dig_P7 = (data[19] << 8) | data[18];
  dig_P8 = (data[21] << 8) | data[20];
  dig_P9 = (data[23] << 8) | data[22];
  dig_H1 = data[24];
  dig_H2 = (data[26] << 8) | data[25];
  dig_H3 = data[27];
  dig_H4 = (data[28] << 4) | (0x0F & data[29]);
  dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
  dig_H6 = data[31];
}

ISR(PCINT0_vect) {
  if (PB3_READ == 0) { // LOW level KEY
    sleep_disable();
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT3);
  }
}

void toSleep() {
  // pins mode
  PB0_IN; PB0_LOW;
  PB1_OUT; PB1_LOW;
  PB2_IN; PB2_LOW;
  PB3_IN; PB3_HIGH; // LOW = OFF res, if HIGH level KEY
  PB4_OUT; PB4_LOW;
  // sleep
  cbi(ADCSRA, ADEN);
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT3);
  sleep_mode();
}

void setup () {
  firstStart = true;
}

void readData()
{
  int i = 0;
  uint32_t data[8];
  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0xF7);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 8);
  while (TinyWireM.available()) {
    data[i] = TinyWireM.read();
    i++;
  }
  pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
  temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
  hum_raw  = (data[6] << 8) | data[7];
  temp_raw = calibration_T(temp_raw);
  pres_raw = (calibration_P(pres_raw) / 133.32) - 5;
  hum_raw = calibration_H(hum_raw) / 1024;
}

void loop () {
  unsigned long curr_millis = millis();
  if (firstStart) {
    toSleep();
    firstStart = false;
    wakeUpTimer = curr_millis;
    showMode = 0;
    showTimer = curr_millis;
    changeMode = true;
    // get data from BME280
    initBME280();
    readData();
    resetBME280();
    OzOled.init();  //инициализация дисплей
    OzOled.setNormalDisplay();      //нормальный режим
    OzOled.setPageMode();           //адресация страничная
    OzOled.sendCommand(0xA1);       //выбор ориентации сверху - вниз
    OzOled.sendCommand(0xC8);       //слева - направо
  }
  // work
  if ((curr_millis - showTimer) >= 4000UL) { // change disp every 4 sec
    showTimer = curr_millis;
    changeMode = true;
    ++showMode;
    if (showMode > 2) {
      showMode = 0;
    }
  }
  if (changeMode) {
    OzOled.clearDisplay();          //очистка дисплея
    switch (showMode) {
      case 1: {
          char str[4] = "";
          str[0] = (pres_raw / 100) + 0x30;
          str[1] = (pres_raw % 100) / 10 + 0x30;
          str[2] = (pres_raw % 100) % 10 + 0x30;
          str[3] = 0x00;
          OzOled.printBigNumber(str, 3, 0);
          break;
        }
      case 2: {
          /*char str[6] = "";
            str[0] = (hum_raw / 10000) + 0x30;
            str[1] = (hum_raw % 10000)/1000 + 0x30;
            str[2] = ((hum_raw % 10000)%1000)/100 + 0x30;
            str[3] = (((hum_raw % 10000)%1000)%100)/10 + 0x30;
            str[4] = (((hum_raw % 10000)%1000)%100)%10 + 0x30;
            str[5] = 0x00;*/
          char str[3] = "";
          str[0] = hum_raw / 10 + 0x30;
          str[1] = hum_raw % 10 + 0x30;
          str[2] = 0x00;
          OzOled.printBigNumber(str, 6, 0);
          break;
        }
      default: { // show temp
          char str[6] = "";
          str[0] = (temp_raw / 1000) + 0x30;
          str[1] = (temp_raw % 1000) / 100 + 0x30;
          str[2] = '.';
          str[3] = ((temp_raw % 1000) % 100) / 10 + 0x30;
          str[4] = ((temp_raw % 1000) % 100) % 10 + 0x30;
          str[5] = 0x00;
          OzOled.printBigNumber(str, 0, 0);
        }
    }
    changeMode = false;
  }
  // OFF show data
  if ((curr_millis - wakeUpTimer) >= 39000UL) { // show 39 sec
    firstStart = true;
    // OFF display
    OzOled.setPowerOff();
    // OFF BME
  }
}

unsigned long int calibration_P(signed long int adc_P)  {
  signed long int var1, var2;
  unsigned long int P;
  var1 = (((signed long int)t_fine) >> 1) - (signed long int)64000;
  var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * ((signed long int)dig_P6);
  var2 = var2 + ((var1 * ((signed long int)dig_P5)) << 1);
  var2 = (var2 >> 2) + (((signed long int)dig_P4) << 16);
  var1 = (((dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((((signed long int)dig_P2) * var1) >> 1)) >> 18;
  var1 = ((((32768 + var1)) * ((signed long int)dig_P1)) >> 15);
  if (var1 == 0)
  {
    return 0;
  }
  P = (((unsigned long int)(((signed long int)1048576) - adc_P) - (var2 >> 12))) * 3125;
  if (P < 0x80000000)
  {
    P = (P << 1) / ((unsigned long int) var1);
  }
  else
  {
    P = (P / (unsigned long int)var1) * 2;
  }
  var1 = (((signed long int)dig_P9) * ((signed long int)(((P >> 3) * (P >> 3)) >> 13))) >> 12;
  var2 = (((signed long int)(P >> 2)) * ((signed long int)dig_P8)) >> 13;
  P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
  return P;
}

unsigned long int calibration_H(signed long int adc_H)  {
  signed long int v_x1;

  v_x1 = (t_fine - ((signed long int)76800));
  v_x1 = (((((adc_H << 14) - (((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) +
            ((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) *
                (((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) *
                ((signed long int) dig_H2) + 8192) >> 14));
  v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
  v_x1 = (v_x1 < 0 ? 0 : v_x1);
  v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
  return (unsigned long int)(v_x1 >> 12);
}

 

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

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

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

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

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

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

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

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

#include <TinyOzOLED.h>
#include <TinyWireM.h>
#include <avr/sleep.h>
#define BME280_ADDRESS 0x76
unsigned long int hum_raw, temp_raw, pres_raw;
signed long int t_fine;

uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
int8_t  dig_H1;
int16_t dig_H2;
int8_t  dig_H3;
int16_t dig_H4;
int16_t dig_H5;
int8_t  dig_H6;

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// PB0 pin 5 - SDA
#define PB0_OUT sbi(DDRB,PB0)
#define PB0_IN cbi(DDRB,PB0)
#define PB0_HIGH sbi(PORTB,PB0)
#define PB0_LOW cbi(PORTB,PB0)
// PB1 pin 6
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
// PB2 pin 7 - SCL
#define PB2_OUT sbi(DDRB,PB2)
#define PB2_IN cbi(DDRB,PB2)
#define PB2_HIGH sbi(PORTB,PB2)
#define PB2_LOW cbi(PORTB,PB2)
// PB3 pin 2 - WakeUp KEY
#define PB3_OUT sbi(DDRB,PB3)
#define PB3_IN cbi(DDRB,PB3)
#define PB3_HIGH sbi(PORTB,PB3)
#define PB3_LOW cbi(PORTB,PB3)
#define PB3_READ bitRead(PINB,PB3)
// PB4 pin 3
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)

boolean firstStart;
unsigned long showTimer;
unsigned long wakeUpTimer;
byte showMode; // 0-temp 1-pres 2-hum
boolean changeMode;

void writeReg(uint8_t reg_address, uint8_t data) {
  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(reg_address);
  TinyWireM.write(data);
  TinyWireM.endTransmission();
}

void initBME280() {

  uint8_t osrs_t = 1;             //Temperature oversampling x 1
  uint8_t osrs_p = 1;             //Pressure oversampling x 1
  uint8_t osrs_h = 2;             //Humidity oversampling x 1
  uint8_t mode = 3;               //Normal mode
  uint8_t t_sb = 5;               //Tstandby 1000ms
  uint8_t filter = 0;             //Filter off
  uint8_t spi3w_en = 0;           //3-wire SPI Disable

  uint8_t ctrl_meas_reg = (osrs_t << 5) | (osrs_p << 2) | mode;
  uint8_t config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en;
  uint8_t ctrl_hum_reg  = osrs_h;
  writeReg(0xF2, ctrl_hum_reg);
  writeReg(0xF4, ctrl_meas_reg);
  writeReg(0xF5, config_reg);
  readTrim();
}

ISR(PCINT0_vect) {
  if (PB3_READ == 0) { // LOW level KEY
    sleep_disable();
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT3);
  }
}

void toSleep() {
  // pins mode
  PB0_IN; PB0_LOW;
  PB1_OUT; PB1_LOW;
  PB2_IN; PB2_LOW;
  PB3_IN; PB3_HIGH; // LOW = OFF res, if HIGH level KEY
  PB4_OUT; PB4_LOW;
  // sleep
  cbi(ADCSRA, ADEN);
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT3);
  sleep_mode();
}

void setup () {
  firstStart = true;
  TinyWireM.begin();
  initBME280();
}

void readData()
{
  int i = 0;
  uint32_t data[8];
  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0xF7);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 8);
  while (TinyWireM.available()) {
    data[i] = TinyWireM.read();
    i++;
  }
  pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
  temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
  hum_raw  = (data[6] << 8) | data[7];
  temp_raw = calibration_T(temp_raw);
  pres_raw = (calibration_P(pres_raw) / 133.32) - 5;
  hum_raw = calibration_H(hum_raw) / 1024;
}

void loop () {
  unsigned long curr_millis = millis();
  if (firstStart) {
    toSleep();
    firstStart = false;
    wakeUpTimer = curr_millis;
    showMode = 0;
    showTimer = curr_millis;
    changeMode = true;
    // get data from BME280
    TinyWireM.begin();
    t_fine = 0;
    readData();
    OzOled.init();  //инициализация дисплей
    OzOled.setNormalDisplay();      //нормальный режим
    OzOled.setPageMode();           //адресация страничная
    OzOled.sendCommand(0xA1);       //выбор ориентации сверху - вниз
    OzOled.sendCommand(0xC8);       //слева - направо
  }
  // work
  if ((curr_millis - showTimer) >= 4000UL) { // change disp every 4 sec
    showTimer = curr_millis;
    changeMode = true;
    ++showMode;
    if (showMode > 2) {
      showMode = 0;
    }
  }
  if (changeMode) {
    OzOled.clearDisplay();          //очистка дисплея
    switch (showMode) {
      case 1: {
          char str[4] = "";
          str[0] = (pres_raw / 100) + 0x30;
          str[1] = (pres_raw % 100) / 10 + 0x30;
          str[2] = (pres_raw % 100) % 10 + 0x30;
          str[3] = 0x00;
          OzOled.printBigNumber(str, 3, 0);
          break;
        }
      case 2: {
          char str[3] = "";
          str[0] = hum_raw / 10 + 0x30;
          str[1] = hum_raw % 10 + 0x30;
          str[2] = 0x00;
          OzOled.printBigNumber(str, 6, 0);
          break;
        }
      default: { // show temp
          char str[6] = "";
          str[0] = (temp_raw / 1000) + 0x30;
          str[1] = (temp_raw % 1000) / 100 + 0x30;
          str[2] = '.';
          str[3] = ((temp_raw % 1000) % 100) / 10 + 0x30;
          str[4] = ((temp_raw % 1000) % 100) % 10 + 0x30;
          str[5] = 0x00;
          OzOled.printBigNumber(str, 0, 0);
        }
    }
    changeMode = false;
  }
  // OFF show data
  if ((curr_millis - wakeUpTimer) >= 40000UL) {
    firstStart = true;
    // OFF display
    OzOled.setPowerOff();
  }
}

unsigned long int calibration_P(signed long int adc_P)  {
  signed long int var1, var2;
  unsigned long int P;
  var1 = (((signed long int)t_fine) >> 1) - (signed long int)64000;
  var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * ((signed long int)dig_P6);
  var2 = var2 + ((var1 * ((signed long int)dig_P5)) << 1);
  var2 = (var2 >> 2) + (((signed long int)dig_P4) << 16);
  var1 = (((dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((((signed long int)dig_P2) * var1) >> 1)) >> 18;
  var1 = ((((32768 + var1)) * ((signed long int)dig_P1)) >> 15);
  if (var1 == 0)
  {
    return 0;
  }
  P = (((unsigned long int)(((signed long int)1048576) - adc_P) - (var2 >> 12))) * 3125;
  if (P < 0x80000000)
  {
    P = (P << 1) / ((unsigned long int) var1);
  }
  else
  {
    P = (P / (unsigned long int)var1) * 2;
  }
  var1 = (((signed long int)dig_P9) * ((signed long int)(((P >> 3) * (P >> 3)) >> 13))) >> 12;
  var2 = (((signed long int)(P >> 2)) * ((signed long int)dig_P8)) >> 13;
  P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
  return P;
}

unsigned long int calibration_H(signed long int adc_H)  {
  signed long int v_x1;

  v_x1 = (t_fine - ((signed long int)76800));
  v_x1 = (((((adc_H << 14) - (((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) +
            ((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) *
                (((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) *
                ((signed long int) dig_H2) + 8192) >> 14));
  v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
  v_x1 = (v_x1 < 0 ? 0 : v_x1);
  v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
  return (unsigned long int)(v_x1 >> 12);
}

void resetBME280() {
  writeReg(0xE0, 0xB6);
}

signed long int calibration_T(signed long int adc_T)
{

  signed long int var1, var2, T;
  var1 = ((((adc_T >> 3) - ((signed long int)dig_T1 << 1))) * ((signed long int)dig_T2)) >> 11;
  var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T >> 4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;

  t_fine = var1 + var2;
  T = (t_fine * 5 + 128) >> 8;
  return T;
}

void readTrim()  {
  uint8_t data[32], i = 0;
  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0x88);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 24);
  while (TinyWireM.available()) {
    data[i] = TinyWireM.read();
    i++;
  }

  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0xA1);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 1);
  data[i] = TinyWireM.read();
  i++;

  TinyWireM.beginTransmission(BME280_ADDRESS);
  TinyWireM.write(0xE1);
  TinyWireM.endTransmission();
  TinyWireM.requestFrom(BME280_ADDRESS, 7);
  while (TinyWireM.available()) {
    data[i] = TinyWireM.read();
    i++;
  }
  dig_T1 = (data[1] << 8) | data[0];
  dig_T2 = (data[3] << 8) | data[2];
  dig_T3 = (data[5] << 8) | data[4];
  dig_P1 = (data[7] << 8) | data[6];
  dig_P2 = (data[9] << 8) | data[8];
  dig_P3 = (data[11] << 8) | data[10];
  dig_P4 = (data[13] << 8) | data[12];
  dig_P5 = (data[15] << 8) | data[14];
  dig_P6 = (data[17] << 8) | data[16];
  dig_P7 = (data[19] << 8) | data[18];
  dig_P8 = (data[21] << 8) | data[20];
  dig_P9 = (data[23] << 8) | data[22];
  dig_H1 = data[24];
  dig_H2 = (data[26] << 8) | data[25];
  dig_H3 = data[27];
  dig_H4 = (data[28] << 4) | (0x0F & data[29]);
  dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
  dig_H6 = data[31];
}

 

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
Да ошибка понятна ...
Clock_andycat:277: error: 'class USI_TWI' has no member named 'read'

     data[i] = TinyWireM.read();
                         ^
Clock_andycat:282: error: 'class USI_TWI' has no member named 'write'

   TinyWireM.write(0xA1);

 

 

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

ulis пишет:

Да ошибка понятна ...
Clock_andycat:277: error: 'class USI_TWI' has no member named 'read'

     data[i] = TinyWireM.read();
                         ^
Clock_andycat:282: error: 'class USI_TWI' has no member named 'write'

   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
#include <DigisparkOLED.h>
#include <Wire.h>



void setup() {
oled.begin();
oled.clear();
oled.setCursor(0, 0);
oled.setFont(FONT8X16);
oled.print(F("Hello, world!"));
}

void loop() {


}
Скетч использует 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

/*
  OzOLED.cpp - 0.96' I2C 128x64 OLED Driver Library
  2014 Copyright (c) OscarLiang.net  All right reserved.
 
  Author: Oscar Liang
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  
  Uses TinyWireM instead of Wire llibrary. For Attiny processors
  Change done by Andreas Spiess, sensorsiot@gmail.com

*/




#include "TinyOzOLED.h"
#include <TinyWireM.h>
#include <avr/pgmspace.h>


// 8x8 Font ASCII 32 - 127 Implemented
// Users can modify this to support more characters(glyphs)
// BasicFont is placed in code memory.

// This font be freely used without any restriction(It is placed in public domain)
const byte BasicFont[][8] PROGMEM = {
	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
	{0x00,0x00,0x5F,0x00,0x00,0x00,0x00,0x00},
	{0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x00},
	{0x00,0x14,0x7F,0x14,0x7F,0x14,0x00,0x00},
	{0x00,0x24,0x2A,0x7F,0x2A,0x12,0x00,0x00},
	{0x00,0x23,0x13,0x08,0x64,0x62,0x00,0x00},
	{0x00,0x36,0x49,0x55,0x22,0x50,0x00,0x00},
	{0x00,0x00,0x05,0x03,0x00,0x00,0x00,0x00},
	{0x00,0x1C,0x22,0x41,0x00,0x00,0x00,0x00},
	{0x00,0x41,0x22,0x1C,0x00,0x00,0x00,0x00},
	{0x00,0x08,0x2A,0x1C,0x2A,0x08,0x00,0x00},
	{0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00},
	{0x00,0xA0,0x60,0x00,0x00,0x00,0x00,0x00},
	{0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00},
	{0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00},
	{0x00,0x20,0x10,0x08,0x04,0x02,0x00,0x00},
	{0x00,0x3E,0x51,0x49,0x45,0x3E,0x00,0x00},
	{0x00,0x00,0x42,0x7F,0x40,0x00,0x00,0x00},
	{0x00,0x62,0x51,0x49,0x49,0x46,0x00,0x00},
	{0x00,0x22,0x41,0x49,0x49,0x36,0x00,0x00},
	{0x00,0x18,0x14,0x12,0x7F,0x10,0x00,0x00},
	{0x00,0x27,0x45,0x45,0x45,0x39,0x00,0x00},
	{0x00,0x3C,0x4A,0x49,0x49,0x30,0x00,0x00},
	{0x00,0x01,0x71,0x09,0x05,0x03,0x00,0x00},
	{0x00,0x36,0x49,0x49,0x49,0x36,0x00,0x00},
	{0x00,0x06,0x49,0x49,0x29,0x1E,0x00,0x00},
	{0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00},
	{0x00,0x00,0xAC,0x6C,0x00,0x00,0x00,0x00},
	{0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00},
	{0x00,0x14,0x14,0x14,0x14,0x14,0x00,0x00},
	{0x00,0x41,0x22,0x14,0x08,0x00,0x00,0x00},
	{0x00,0x02,0x01,0x51,0x09,0x06,0x00,0x00},
	{0x00,0x32,0x49,0x79,0x41,0x3E,0x00,0x00},
	{0x00,0x7E,0x09,0x09,0x09,0x7E,0x00,0x00},
	{0x00,0x7F,0x49,0x49,0x49,0x36,0x00,0x00},
	{0x00,0x3E,0x41,0x41,0x41,0x22,0x00,0x00},
	{0x00,0x7F,0x41,0x41,0x22,0x1C,0x00,0x00},
	{0x00,0x7F,0x49,0x49,0x49,0x41,0x00,0x00},
	{0x00,0x7F,0x09,0x09,0x09,0x01,0x00,0x00},
	{0x00,0x3E,0x41,0x41,0x51,0x72,0x00,0x00},
	{0x00,0x7F,0x08,0x08,0x08,0x7F,0x00,0x00},
	{0x00,0x41,0x7F,0x41,0x00,0x00,0x00,0x00},
	{0x00,0x20,0x40,0x41,0x3F,0x01,0x00,0x00},
	{0x00,0x7F,0x08,0x14,0x22,0x41,0x00,0x00},
	{0x00,0x7F,0x40,0x40,0x40,0x40,0x00,0x00},
	{0x00,0x7F,0x02,0x0C,0x02,0x7F,0x00,0x00},
	{0x00,0x7F,0x04,0x08,0x10,0x7F,0x00,0x00},
	{0x00,0x3E,0x41,0x41,0x41,0x3E,0x00,0x00},
	{0x00,0x7F,0x09,0x09,0x09,0x06,0x00,0x00},
	{0x00,0x3E,0x41,0x51,0x21,0x5E,0x00,0x00},
	{0x00,0x7F,0x09,0x19,0x29,0x46,0x00,0x00},
	{0x00,0x26,0x49,0x49,0x49,0x32,0x00,0x00},
	{0x00,0x01,0x01,0x7F,0x01,0x01,0x00,0x00},
	{0x00,0x3F,0x40,0x40,0x40,0x3F,0x00,0x00},
	{0x00,0x1F,0x20,0x40,0x20,0x1F,0x00,0x00},
	{0x00,0x3F,0x40,0x38,0x40,0x3F,0x00,0x00},
	{0x00,0x63,0x14,0x08,0x14,0x63,0x00,0x00},
	{0x00,0x03,0x04,0x78,0x04,0x03,0x00,0x00},
	{0x00,0x61,0x51,0x49,0x45,0x43,0x00,0x00},
	{0x00,0x7F,0x41,0x41,0x00,0x00,0x00,0x00},
	{0x00,0x02,0x04,0x08,0x10,0x20,0x00,0x00},
	{0x00,0x41,0x41,0x7F,0x00,0x00,0x00,0x00},
	{0x00,0x04,0x02,0x01,0x02,0x04,0x00,0x00},
	{0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00},
	{0x00,0x01,0x02,0x04,0x00,0x00,0x00,0x00},
	{0x00,0x20,0x54,0x54,0x54,0x78,0x00,0x00},
	{0x00,0x7F,0x48,0x44,0x44,0x38,0x00,0x00},
	{0x00,0x38,0x44,0x44,0x28,0x00,0x00,0x00},
	{0x00,0x38,0x44,0x44,0x48,0x7F,0x00,0x00},
	{0x00,0x38,0x54,0x54,0x54,0x18,0x00,0x00},
	{0x00,0x08,0x7E,0x09,0x02,0x00,0x00,0x00},
	{0x00,0x18,0xA4,0xA4,0xA4,0x7C,0x00,0x00},
	{0x00,0x7F,0x08,0x04,0x04,0x78,0x00,0x00},
	{0x00,0x00,0x7D,0x00,0x00,0x00,0x00,0x00},
	{0x00,0x80,0x84,0x7D,0x00,0x00,0x00,0x00},
	{0x00,0x7F,0x10,0x28,0x44,0x00,0x00,0x00},
	{0x00,0x41,0x7F,0x40,0x00,0x00,0x00,0x00},
	{0x00,0x7C,0x04,0x18,0x04,0x78,0x00,0x00},
	{0x00,0x7C,0x08,0x04,0x7C,0x00,0x00,0x00},
	{0x00,0x38,0x44,0x44,0x38,0x00,0x00,0x00},
	{0x00,0xFC,0x24,0x24,0x18,0x00,0x00,0x00},
	{0x00,0x18,0x24,0x24,0xFC,0x00,0x00,0x00},
	{0x00,0x00,0x7C,0x08,0x04,0x00,0x00,0x00},
	{0x00,0x48,0x54,0x54,0x24,0x00,0x00,0x00},
	{0x00,0x04,0x7F,0x44,0x00,0x00,0x00,0x00},
	{0x00,0x3C,0x40,0x40,0x7C,0x00,0x00,0x00},
	{0x00,0x1C,0x20,0x40,0x20,0x1C,0x00,0x00},
	{0x00,0x3C,0x40,0x30,0x40,0x3C,0x00,0x00},
	{0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00},
	{0x00,0x1C,0xA0,0xA0,0x7C,0x00,0x00,0x00},
	{0x00,0x44,0x64,0x54,0x4C,0x44,0x00,0x00},
	{0x00,0x08,0x36,0x41,0x00,0x00,0x00,0x00},
	{0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},
	{0x00,0x41,0x36,0x08,0x00,0x00,0x00,0x00},
	{0x00,0x02,0x01,0x01,0x02,0x01,0x00,0x00},
	{0x00,0x02,0x05,0x05,0x02,0x00,0x00,0x00} 
};


// Big numbers font, from 0 to 9 - 96 bytes each.
const byte bigNumbers [][96] PROGMEM = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0,
0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xC1, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x83, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xC1, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE1, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x81, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x87,
0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x81, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x87,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0x81, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x87,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xE1,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE1, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x87, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x87,
0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00},

{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3C, 0x7E, 0x7E, 0x7E, 0x7E, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
};

// ====================== LOW LEVEL =========================
void OzOLED::sendCommand(byte command){
	TinyWireM.beginTransmission(OLED_ADDRESS); // begin transmitting
	TinyWireM.send(OzOLED_COMMAND_MODE);//data mode
	TinyWireM.send(command);
	TinyWireM.endTransmission();    // stop transmitting
}

void OzOLED::sendData(byte data){
	TinyWireM.beginTransmission(OLED_ADDRESS); // begin transmitting
	TinyWireM.send(OzOLED_DATA_MODE);//data mode
	TinyWireM.send(data);
	TinyWireM.endTransmission();    // stop transmitting
}

void OzOLED::printChar(char C, byte X, byte Y){
	if ( X < 128 )
		setCursorXY(X, Y);
	//Ignore unused ASCII characters. Modified the range to support multilingual characters.
    if(C < 32 || C > 127)
		C='*'; //star - indicate characters that can't be displayed
	byte src_b, b_out, b_tmp;
    for(byte i=0; i<8; i++) {
		src_b = pgm_read_byte(&BasicFont[C-32][i]);
					b_out = (src_b & 0x01) << 1;
					b_tmp = (src_b & 0x02) << 2;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x04) << 3;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x08) << 4;
					b_out |= b_tmp;
       //read bytes from code memory
       sendData(b_out); //font array starts at 0, ASCII starts at 32. Hence the translation
    }
	setCursorXY(X, ++Y);
    for(byte i=0; i<8; i++) {
		src_b = pgm_read_byte(&BasicFont[C-32][i]);
					b_out = (src_b & 0x10) >> 3;
					b_tmp = (src_b & 0x20) >> 2;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x40) >> 1;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x80);
					b_out |= b_tmp;
       //read bytes from code memory
       sendData(b_out); //font array starts at 0, ASCII starts at 32. Hence the translation
    }
}

void OzOLED::printString(const char *String, byte X, byte Y, byte numChar){
	if ( X < 128 )
		setCursorXY(X, Y);
	byte count=0;
    while(String[count] && count<numChar){
		printChar(String[count++],X,Y);  
		++X;
	}
}

byte OzOLED::printNumber(long long_num, byte X, byte Y){
	if ( X < 128 )
		setCursorXY(X, Y);
	byte char_buffer[10] = "";
	byte i = 0;
	byte f = 0; // number of characters
	if (long_num < 0) {
		f++;
		printChar('-',X,Y);
		long_num = -long_num;
	} 
	else if (long_num == 0) {
		f++;
		printChar('0',X,Y);
		return f;
	} 
	while (long_num > 0) {
		char_buffer[i++] = long_num % 10;
		long_num /= 10;
	}
	f += i;
	for(; i > 0; i--) {
		printChar('0'+ char_buffer[i - 1],(X+(f-i)),Y);
	}
	return f;
}

byte OzOLED::printNumber(float float_num, byte prec, byte X, byte Y){
	if ( X < 128 )
		setCursorXY(X, Y);
// prec - 6 maximum
	byte num_int = 0;
	byte num_frac = 0;
	byte num_extra = 0;
	long d = float_num; // get the integer part
	float f = float_num - d; // get the fractional part
	if (d == 0 && f < 0.0){
		printChar('-',X,Y);
		++X;
		num_extra++;
		printChar('0',X,Y);
		++X;
		num_extra++;
		f *= -1;
	}
	else if (d < 0 && f < 0.0){
		num_int = printNumber(d,X,Y); // count how many digits in integer part
		X += num_int;
		f *= -1;
	}
	else{
		num_int = printNumber(d,X,Y); // count how many digits in integer part
		X += num_int;
	}
	// only when fractional part > 0, we show decimal point
	if (f > 0.0){
		printChar('.',X,Y);
		++X;
		num_extra++;
		long f_shift = 1;
		if (num_int + prec > 8) 
			prec = 8 - num_int;
		for (byte j=0; j<prec; j++){
			f_shift *= 10;
		}
		num_frac = printNumber((long)(f*f_shift),X,Y); // count how many digits in fractional part
	}
	return num_int + num_frac + num_extra;
}

void OzOLED::printBigNumber(const char *number, byte X, byte Y, byte numChar){
// big number pixels: 24 x 32
 // Y - page
	byte column = 0;
	byte count = 0;
	byte onech[96];
	while(number[count] && count<numChar){
		setCursorXY(X, Y);
		// update for China OLED display 128*32
		byte src_b, b_out, b_tmp;
		for (byte i=0; i<4; ++i) {
			byte j;
			for (j=0; j<24; ++j) {
				if(number[count] < 46 || number[count] > 58)	
					sendData(0);
				else 	{			
					src_b = pgm_read_byte(&bigNumbers[number[count]-46][(i*24)+j]);
					onech[(i*24)+j] = src_b;
					b_out = (src_b & 0x01) << 1;
					b_tmp = (src_b & 0x02) << 2;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x04) << 3;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x08) << 4;
					b_out |= b_tmp;
					sendData(b_out);
				}
			}
			column = 0;
			setCursorXY(X, ++Y);
			for (j=0; j<24; ++j) {
				if(number[count] < 46 || number[count] > 58)	
					sendData(0);
				else 	{			
					//src_b = pgm_read_byte(&bigNumbers[number[count]-46][(i*24)+j]); 
					src_b = onech[(i*24)+j];
					b_out = (src_b & 0x10) >> 3;
					b_tmp = (src_b & 0x20) >> 2;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x40) >> 1;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x80);
					b_out |= b_tmp;
					sendData(b_out);
				}
			}
			column = 0;
			setCursorXY(X, ++Y);
		}
		count++;
		X = X + 3;
		Y = Y - 8;
	}
}

void OzOLED::drawBitmap(const byte *bitmaparray, byte X, byte Y, byte width, byte height){
// max width = 16
// max height = 8
	setCursorXY( X, Y );
	byte column = 0; 
	for(int i=0; i<width*8*height; i++) {  
		sendData(pgm_read_byte(&bitmaparray[i]));
		if(++column == width*8) {
			column = 0;
			setCursorXY( X, ++Y );
		} 
	}
}

// =================== High Level ===========================

void OzOLED::init(){
	TinyWireM.begin();
/*	// upgrade to 400KHz! (only use when your other i2c device support this speed)
	if (I2C_400KHZ){
		// save I2C bitrate (default 100Khz)
		byte twbrbackup = TWBR;
		TWBR = 12; 
		//TWBR = twbrbackup;
		//Serial.println(TWBR, DEC);
		//Serial.println(TWSR & 0x3, DEC);
	}*/
    setPowerOff(); 	//display off
    delay(10);
    setPowerOn();	//display on
    delay(10); 
    setNormalDisplay();  //default Set Normal Display
	setPageMode();	// default addressing mode
	clearDisplay();
	setCursorXY(0,0);
	sendCommand(0x8d); //Charge Pump
    sendCommand(0x14);
}

void OzOLED::setCursorXY(byte X, byte Y){
	// Y - 1 unit = 1 page (8 pixel rows)
	// X - 1 unit = 8 pixel columns
    sendCommand(0x00 + (8*X & 0x0F)); 		//set column lower address
    sendCommand(0x10 + ((8*X>>4)&0x0F)); 	//set column higher address
	sendCommand(0xB0 + Y); 					//set page address
}


void OzOLED::clearDisplay()	{
	for(byte page=0; page<8; page++) {	
		setCursorXY(0, page);     
		for(byte column=0; column<128; column++){  //clear all columns
			sendData(0x00);    
		}
	}
	setCursorXY(0,0);  
}

/*
void OzOLED::clearPage(byte page)	{
	// clear page and set cursor at beginning of that page

	setCursorXY(0, page);    
	for(byte column=0; column<128; column++){  //clear all columns
		sendData(0x00);    
	}
	
}
*/


void OzOLED::setInverseDisplay(){
	sendCommand(OzOLED_CMD_INVERSE_DISPLAY);
}

void OzOLED::setNormalDisplay(){
	sendCommand(OzOLED_CMD_NORMAL_DISPLAY);
}

void OzOLED::setPowerOff(){
	sendCommand(OzOLED_CMD_DISPLAY_OFF);
}

void OzOLED::setPowerOn(){
	sendCommand(OzOLED_CMD_DISPLAY_ON);
}

void OzOLED::setBrightness(byte Brightness){
	sendCommand(OzOLED_CMD_SET_BRIGHTNESS);
	sendCommand(Brightness);
}

void OzOLED::setPageMode(){
	addressingMode = PAGE_ADDRESSING;
	sendCommand(0x20); 				//set addressing mode
	sendCommand(PAGE_ADDRESSING); 	//set page addressing mode
}

void OzOLED::setHorizontalMode(){
	addressingMode = HORIZONTAL_ADDRESSING;
	sendCommand(0x20); 				//set addressing mode
	sendCommand(HORIZONTAL_ADDRESSING); 	//set page addressing mode
}

// startscrollright
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// scrollRight(0x00, 0x0F)  - start - stop
void OzOLED::scrollRight(byte start, byte end, byte speed){
    sendCommand(OzOLED_RIGHT_SCROLL);  //Horizontal Scroll Setup
    sendCommand(0x00);	// dummy byte 
    sendCommand(start);	// start page address
    sendCommand(speed);	// set time interval between each scroll
    sendCommand(end);	// end page address
    sendCommand(0x01);  
    sendCommand(0xFF);
    sendCommand(0x2f);  //active scrolling
}

// startscrollleft
// Activate a right handed scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(0x00, 0x0F)   - start - stop
void OzOLED::scrollLeft(byte start, byte end, byte speed){
    sendCommand(OzOLED_LEFT_SCROLL);  //Horizontal Scroll Setup
    sendCommand(0x00);	// dummy byte
    sendCommand(start);	// start page address
    sendCommand(speed);	// set time interval between each scroll
    sendCommand(end);	// end page address
    sendCommand(0x01);  
    sendCommand(0xFF);  
    sendCommand(0x2f);  //active scrolling
}

// startscrolldiagright
// Activate a diagonal scroll for rows start through stop
// Hint, the display is 16 rows tall. To scroll the whole display, run:
// display.scrollright(0x00, 0x0F) 
void OzOLED::scrollDiagRight(){
        sendCommand(OzOLED_SET_VERTICAL_SCROLL_AREA);        
        sendCommand(0X00);
        sendCommand(OzOLED_Max_Y);
        sendCommand(OzOLED_VERTICAL_RIGHT_SCROLL); //Vertical and Horizontal Scroll Setup
        sendCommand(0X00); 	//dummy byte
        sendCommand(0x00);	 //define page0 as startpage address
        sendCommand(0X00);	//set time interval between each scroll ste as 6 frames
        sendCommand(0x07);	//define page7 as endpage address
        sendCommand(0X01);	//set vertical scrolling offset as 1 row
        sendCommand(OzOLED_CMD_ACTIVATE_SCROLL); //active scrolling
}

void OzOLED::scrollDiagLeft(){
        sendCommand(OzOLED_SET_VERTICAL_SCROLL_AREA);        
        sendCommand(0X00);
        sendCommand(OzOLED_Max_Y);
        sendCommand(OzOLED_VERTICAL_LEFT_SCROLL); //Vertical and Horizontal Scroll Setup
        sendCommand(0X00); //dummy byte
        sendCommand(0x00);	 //define page0 as startpage address
        sendCommand(0X00);	//set time interval between each scroll ste as 6 frames
        sendCommand(0x07);	//define page7 as endpage address
        sendCommand(0X01);	//set vertical scrolling offset as 1 row
        sendCommand(OzOLED_CMD_ACTIVATE_SCROLL); //active scrolling
}


void OzOLED::setActivateScroll(byte direction, byte startPage, byte endPage, byte scrollSpeed){
/*
This function is still not complete, we need more testing also.
Use the following defines for 'direction' :
 Scroll_Left			
 Scroll_Right			
For Scroll_vericle, still need to debug more... 
Use the following defines for 'scrollSpeed' :
 Scroll_2Frames		
 Scroll_3Frames
 Scroll_4Frames
 Scroll_5Frames	
 Scroll_25Frames
 Scroll_64Frames
 Scroll_128Frames
 Scroll_256Frames
*/
	if(direction == Scroll_Right) {
		//Scroll Right
		sendCommand(0x26);
	}
	else {
		//Scroll Left  
		sendCommand(0x27);
	}
	/*
	else if (direction == Scroll_Up ){
		//Scroll Up  
		sendCommand(0x29);
	}
	else{
		//Scroll Down  
		sendCommand(0x2A);
	}
	*/
	sendCommand(0x00);//dummy byte
	sendCommand(startPage);
	sendCommand(scrollSpeed);	
	sendCommand(endPage);		// for verticle scrolling, use 0x29 as command, endPage should = start page = 0
	/*
	if(direction == Scroll_Up) {
		sendCommand(0x01);
	}
	*/
	sendCommand(OzOLED_CMD_ACTIVATE_SCROLL);
}

void OzOLED::setDeactivateScroll(){
	sendCommand(OzOLED_CMD_DEACTIVATE_SCROLL);
}

OzOLED OzOled;  // Preinstantiate Objects

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

void OzOLED::printBigNumber(const char *number, byte X, byte Y, byte numChar){
// big number pixels: 24 x 32
 // Y - page
	byte column = 0;
	byte count = 0;
	byte onech[96];
	while(number[count] && count<numChar){
		setCursorXY(X, Y);
		// update for China OLED display 128*32
		byte src_b, b_out, b_tmp;
		for (byte i=0; i<4; ++i) {
			byte j;
			for (j=0; j<24; ++j) {
				if(number[count] < 46 || number[count] > 58)	
					sendData(0);
				else 	{			
					src_b = pgm_read_byte(&bigNumbers[number[count]-46][(i*24)+j]);
					onech[(i*24)+j] = src_b;
					b_out = (src_b & 0x01) << 1;
					b_tmp = (src_b & 0x02) << 2;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x04) << 3;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x08) << 4;
					b_out |= b_tmp;
					sendData(b_out);
				}
			}
			column = 0;
			setCursorXY(X, ++Y);
			for (j=0; j<24; ++j) {
				if(number[count] < 46 || number[count] > 58)	
					sendData(0);
				else 	{			
					//src_b = pgm_read_byte(&bigNumbers[number[count]-46][(i*24)+j]); 
					src_b = onech[(i*24)+j];
					b_out = (src_b & 0x10) >> 3;
					b_tmp = (src_b & 0x20) >> 2;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x40) >> 1;
					b_out |= b_tmp;
					b_tmp = (src_b & 0x80);
					b_out |= b_tmp;
					sendData(b_out);
				}
			}
			column = 0;
			setCursorXY(X, ++Y);
		}
		count++;
		X = X + 3;
		Y = Y - 8;
	}
}

 

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сек выдать точную температуру, а он по несколько десятых изменяет и то при нажатии на кнопку.