Attiny85 - Вопрос по Дисплею I2C

ViDi79

✩✩✩✩✩✩✩
1 Окт 2023
30
1
Ребят подскажите кто сталкивался в подобным

Собрал я схему и написал скеч для Attiny85. Проект имеет Дисплей I2C, кнопку, одна ножка считает прерывание, и еще одна ножка определяет состояние по изменению сопротивления, еще при отключении питания последние показания записывались в ЕЕПРОМ. Работа проекта задумывалась с дисплеем и без него.
Наткнулся на один момент непонятный для меня. С дисплеем все отрабатывает как и задумывалось, но без Дисплея нечего не работает. В чем может быть причина? Или в каком месте скеча она появляется? Библиотеку Дисплея я использовал Tiny4kOLED.h. Может другую библиотеку посоветуете или на строчке инициализации появляется проблема? Или может когда в скече отправляю данные на дисплей? Может кто сталкивался с подобным? Такое ощущение, что зависает Тинька. Может мне Аттини85 какая то левая попалась?
 
Изменено:

viktor1703

★★★✩✩✩✩
9 Дек 2021
603
143
С дисплеем все отрабатывает как и задумывалось, но без Дисплея нечего не работает.
Когда я в свой хрустальный шар смотрю, то мне всё понятно, а когда без него, то ничего не работает. Не подскажете
В чем может быть причина?
в каком месте скеча
Форумчанам его, скетч, нужно выдумать, или он уже выдуман, но очень секретный?
 

ViDi79

✩✩✩✩✩✩✩
1 Окт 2023
30
1
Вопрос не в написанном скече, а в том, что если устройство запустить с отсутствующем дисплеем, что происходит с Аттини85? До loop вообще доходит? Или может в loop когда отправляешь данные на дисплей, Тинька зависает? На Тиньки Serial.begin даже для отладки не запустить. Вот и задаю вопрос, может кто сталкивался и понял, что происходит с Тинькой.
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
447
130
@ViDi79,
Я с таким не сталкивался. Но ваши слова - "До loop вообще доходит? ", "На Тиньки Serial.begin даже для отладки не запустить." были бы нагляднее с примером. Хотя бы кусок до loop, в котором вывод в сериал работает при подключенном дисплее и не работает с отключенным.
 

viktor1703

★★★✩✩✩✩
9 Дек 2021
603
143
Или может в loop когда отправляешь данные на дисплей, Тинька зависает?
Где скетч? Что он такой секретный? Никто же не знает что вы там прописали. Может у вас в коде так и предписано. Так что хватит сотрясать воздух и требовать становиться экстрасенсами. Хотите помощи давайте скетч. Если он такой секретный, то давайте кусок кода, где по вашему начинаются проблемы. И нечего тут гадать, это не хиромантия, а электроника. Микроконтроллер не может ничего сам решать, как вы указали ему работать, так он и делает. Другое дело, что вы не совсем понимаете как вы ему указали.
 

ViDi79

✩✩✩✩✩✩✩
1 Окт 2023
30
1
Выкладываю. Не судите строга, выкладываю то как он выглядит на сегодняшний момент. Со всеми тестами и экспериментами.

C++:
#include <TinyWireM.h>
#include <Tiny4kOLED.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#define REFERENCE 1.1 //Для измерения В аккумулятора
int procent;//процент заряда аккума
volatile int pat; //шарики
int pot = 500;
unsigned long last_time; // время милис
float ir; //флаг изменеия
byte hu;
bool it = 0; //очищает 10-
bool iy = 0; //очищает 100-
byte iee = 0; // для еепром
int itee = 0; // отладка
bool ip = 0; // чтоб не считал 0--
bool ipo = 0; //для отладки еепрома боол
int ttt = 0; // отладка

//для измерение батарейки. Снятие показаний
uint16_t getADC(void) { 
  ADCSRA = (0x01 << ADEN) | (0x01 << ADPS2) | (0x01 << ADPS1) | (0x01 << ADPS0);
  ADMUX = (0x01 << MUX3) | (0x01 << MUX2);
  _delay_ms(20); // стояла 2мс
  ADCSRA |= (0x01 << ADSC);
  while (ADCSRA & (0x01 << ADSC));
  return (uint16_t)ADCL | ((uint16_t)ADCH << 8);
}
//для измерение батарейки. Перевод в показания В
float adcToVcc(uint16_t adc) {
  return (REFERENCE * 1023.0) / adc;
}
// ============================================================================
void setup() {
  GIMSK = 0b00100000;    // turns on pin change interrupts
  PCMSK = 0b00000010;    // turn on interrupts on pins PB0, PB1, &amp;amp; PB4
  sei();                 // enables interrupts
  pat = eeprom_read_word(30);  //еепром. Чтение ЕЕПРОМ
  itee = eeprom_read_word(50);   //еепром отладка
  // This example is for a 128x64 screen Для дисплея
  oled.begin(128, 64, sizeof(tiny4koled_init_128x64br), tiny4koled_init_128x64br);
  oled.clear();
  oled.on();
  pinMode(PB4, INPUT); //Ресет
  delay (300);
  if (ip == 0){
    ip = 1;
    if (analogRead(A3) > 600){ // при первом примыкании минусует 4 шара
      if (pat >= 4);{
        pat = pat - 4;
        if (pat <= 0) {
          pat = 0;
        } 
      } 
    }
  }
}

//-------------------------------------------------------------------------------------------------------
void loop() {
  if (digitalRead(PB4) == 1){
    if (ipo == 0){
      eeprom_update_word(50, pat);
      ipo++;
    }
    pat = 0;
    oled.clear();
  }
// отображение % заряда аккумулятора
  if (millis() - last_time > 500) {
    last_time = millis();
    procent = ((adcToVcc(getADC()) - 2.5)/1.1)*100;
    //отображение заряда аккумулятора
    oled.setFont(FONT6X8);  // шрифт
    oled.setCursor(35, 23);
    oled.print("% "); oled.print (procent);
    oled.setCursor(35, 22);
    //ttt = eeprom_read_word(30);
    // инфа для отладки на дисплей.
    oled.print (analogRead(A3));  //для теста
    oled.setCursor(80, 22);
    oled.print (iee);
    oled.setCursor(60, 22); //для теста через еепром какое сопротивление
    oled.print (itee);
    if (analogRead(A3) <= 600){ //  шары +
      oled.setFont(FONT6X8);
      oled.setCursor(80, 23);
      oled.print ("L");
    } else {
      oled.setFont(FONT6X8); // шары -
      oled.setCursor(80, 23);
      oled.print ("P");
    }
    // отладочная информация
  }
  //запись
  if (analogRead(A3) <= 480){ //запись 520
    if (iee == 0) {
      eeprom_update_word(30, pat);
      iee = 1;
    }
  }
 
 
  // Отображение на дисплеи количество шаров
  if (pot != pat){
    pot = pat;
    oled.setFontX2Smooth(FONT8X16CAPS); // шрифт
    oled.setCursor(45, 2);
    oled.print(pat);
 
     // количестко шаров обнуление лишних нулей на дисплеи с 100 в 10, и с 10 в 1
    if (pat >= 10){
      it = 1;
    }
    if (pat <= 9){
      if (it==1) {
        oled.setFontX2Smooth(FONT8X16CAPS); // шрифт
        oled.setCursor(45, 2);
        oled.print("9 ");
        it = 0;
      }
    }
      if (pat >= 100){
      iy = 1;
    }
    if (pat <= 99){
      if (iy==1) {
        oled.setFontX2Smooth(FONT8X16CAPS); // шрифт
        oled.setCursor(45, 2);
        oled.print("99 ");
        iy = 0;
      }
    }
   
  }
}

// Интеруп ИК подсчета.
ISR(PCINT0_vect){
  if((PINB & 0b00000010) == 0 ) { //читает порт на 1 или 0
    if (millis() - last_time > 6) {
      last_time = millis();
      if (analogRead(A3) <= 600){ 
        pat++;
      } else {
        if (pat > 0) {
          pat--;     
        }                    
      }
    } 
  }
}
Скеч один. Но задумывалось запуск с Дисплеем, и запуск без дисплея.
 
Изменено:

viktor1703

★★★✩✩✩✩
9 Дек 2021
603
143
По моему скромному мнению тут виновата используемая библиотека Tiny4kOLED для дисплея. Из-за неё, как вы говорите, происходит зависание. На самом деле микроконтроллер ждет ответа от I2C устройства. Попробуйте в дефайнах прописать
C++:
#define TINY4KOLED_QUICK_BEGIN
 

Mestniy96

✩✩✩✩✩✩✩
14 Дек 2019
14
3
Когда дисплей не подключен, код инициализирует oled и выполняет операции с ним. В библиотеке Tiny4kOLED.h нет встроенной проверки подключения дисплея, и если дисплей физически не подключен, TinyWireM может зависнуть при ожидании отклика.
 

ViDi79

✩✩✩✩✩✩✩
1 Окт 2023
30
1
По моему скромному мнению тут виновата используемая библиотека Tiny4kOLED для дисплея. Из-за неё, как вы говорите, происходит зависание. На самом деле микроконтроллер ждет ответа от I2C устройства. Попробуйте в дефайнах прописать
C++:
#define TINY4KOLED_QUICK_BEGIN
Как вариант, но это может выльется в другие проблемы. Дисплей не на постоянной основе висеть будет. Скорее всего со временем из за дребезга Дисплей вообще перестанет загружаться.

А если вариант - Пропустить строку инициализации при отсутствие дисплея? Наверно и в loop придется все обращение к Дисплею обходить.
 

Mestniy96

✩✩✩✩✩✩✩
14 Дек 2019
14
3
@ViDi79, точно не знаю, но судя по библиотеке можно проверять наличие ответ через beginTransmission.
 

ViDi79

✩✩✩✩✩✩✩
1 Окт 2023
30
1
@ViDi79, точно не знаю, но судя по библиотеке можно проверять наличие ответ через beginTransmission.
Если честно я в Wire так глубоко не вникал. наверно попробую с начало просто не инициализировать дисплей при отсутствие его. Посмотрю, что дальше будет.
 

viktor1703

★★★✩✩✩✩
9 Дек 2021
603
143
В библиотеке Tiny4kOLED.h нет встроенной проверки подключения дисплея
Ну так у нее нет, но она подтягивает библиотеку Tiny4kOLED_tiny-i2c.h, в которой есть такие стиоки

C++:
static bool tiny4koled_beginTransmission_tinyi2c(void) {
    return TinyI2C.start(SSD1306, 0);
}

static void tiny4koled_begin_tinyi2c(void) {
    TinyI2C.init();
#ifndef TINY4KOLED_QUICK_BEGIN
    while (!tiny4koled_beginTransmission_tinyi2c()) {
        delay(10);
    }
    datacute_endTransmission_tinyi2c();
Вот, по ходу, они и не дают. А может и не только они.
 
  • Лойс +1
Реакции: Mestniy96

Mestniy96

✩✩✩✩✩✩✩
14 Дек 2019
14
3
Может добавить проверку таким образом? Не знаю - поможет ли.

C++:
void setup() {
  TinyWireM.begin();


  TinyWireM.beginTransmission(0x3C);  // Адрес
  if (TinyWireM.endTransmission() == 0) {
    displayConnected = true;
    oled.begin(128, 64, sizeof(tiny4koled_init_128x64br), tiny4koled_init_128x64br);
    oled.clear();
    oled.on();
  }
}

C++:
void loop() {
  if (displayConnected) {
    oled.setFont(FONT6X8);
    oled.setCursor(35, 23);
    oled.print("% ");
    oled.print(procent);
  }
}
 
  • Лойс +1
Реакции: ViDi79

ViDi79

✩✩✩✩✩✩✩
1 Окт 2023
30
1
Ребят, я в setup инициализацию дисплея отключил при его отсутствии с помощью IF. Слава богу схема позволяет определить его наличие. Даже в loop обращение к дисплею не отключал и все заработало. Наверно в loop тоже лучше обходы дописать с строкам oled. . Как думаете?
 

ViDi79

✩✩✩✩✩✩✩
1 Окт 2023
30
1
Может добавить проверку таким образом? Не знаю - поможет ли.

C++:
void setup() {
  TinyWireM.begin();


  TinyWireM.beginTransmission(0x3C);  // Адрес
  if (TinyWireM.endTransmission() == 0) {
    displayConnected = true;
    oled.begin(128, 64, sizeof(tiny4koled_init_128x64br), tiny4koled_init_128x64br);
    oled.clear();
    oled.on();
  }
}

C++:
void loop() {
  if (displayConnected) {
    oled.setFont(FONT6X8);
    oled.setCursor(35, 23);
    oled.print("% ");
    oled.print(procent);
  }
}
Хм.... интересный программный вариант. Если кто возьмет это вариант на заметку, проверяйте адрес своего дисплея, он не всегда (0x3C)
 
Изменено:
  • Лойс +1
Реакции: Mestniy96