51

Re: attiny13

5Вольт. Третья нога, по схеме, подтянута к питанию.

52

Re: attiny13

Добавил паузы после нажатия кнопки

unsigned int u;
byte input;

void setup() {
 /// конфигурация АЦП 
   ADMUX |= (1<<MUX1);// ADC2 (PB4) input
   ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIF);
   ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);// Division Factor 128
 ///
   DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3);// пины PB0-PB3 как выходы
   
}
 

void loop() {
  while((ADCSRA & (1 << ADIF)) == 0);
   u = (ADCL|ADCH << 8);

 if(u>60 && u<160){input=0;delay(200);}  
 if(u>160 && u<260){input=1;delay(200);}  
 if(u>260 && u<460){input=2;delay(200);}
 if(u>460 && u<600){input=3;delay(200);}  

  

 switch(input){
  case 0: PORTB |= (1<<PB0);PORTB &=~(1 << PB1)|(1 << PB2)|(1 << PB3); break;
  case 1: PORTB |= (1<<PB1);PORTB &=~(1 << PB0)|(1 << PB2)|(1 << PB3); break;
  case 2: PORTB |= (1<<PB2);PORTB &=~(1 << PB0)|(1 << PB1)|(1 << PB3); break;
  case 3: PORTB |= (1<<PB3);PORTB &=~(1 << PB0)|(1 << PB1)|(1 << PB2); break;
  }        
}

53

Re: attiny13

Если Вы меняли делитель, то измерьте напряжение кнопок и опубликуйте их.

54

Re: attiny13

Да, поменял
Теперь  при нажатии кнопок 0,47В-1,27В-1,64В-2,07В.
При отпускании 5В.

55

Re: attiny13

unsigned int u;
byte input;

void setup() {
 /// конфигурация АЦП 
   ADMUX |= (1<<MUX1);// ADC2 (PB4) input
   ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIF);
   ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);// Division Factor 128
 ///
   DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3);// пины PB0-PB3 как выходы
   
}
 

void loop() {
  while((ADCSRA & (1 << ADIF)) == 0);
   u = (ADCL|ADCH << 8);

 if(u>50 && u<150){input=0;delay(200);}  
 if(u>150 && u<300){input=1;delay(200);}  
 if(u>300 && u<400){input=2;delay(200);}
 if(u>400 && u<600){input=3;delay(200);}  

  

 switch(input){
  case 0: PORTB |= (1<<PB0);PORTB &=~(1 << PB1)|(1 << PB2)|(1 << PB3); break;
  case 1: PORTB |= (1<<PB1);PORTB &=~(1 << PB0)|(1 << PB2)|(1 << PB3); break;
  case 2: PORTB |= (1<<PB2);PORTB &=~(1 << PB0)|(1 << PB1)|(1 << PB3); break;
  case 3: PORTB |= (1<<PB3);PORTB &=~(1 << PB0)|(1 << PB1)|(1 << PB2); break;
  }        
}

56 (2024-01-16 19:43:26 отредактировано Karl2233)

Re: attiny13

неа.
бывает включены по 2-3 выхода.

может фьюзы? может третью ногу надо к земле через 10к, а не к 5 Вольтам?

57

Re: attiny13

Попробуйте этот код:

unsigned int u;
byte input;

void setup() {
 /// конфигурация АЦП 
   ADMUX |= (1<<MUX1);// ADC2 (PB4) input
   ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIF);
   ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);// Division Factor 128
 ///
   DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3);// пины PB0-PB3 как выходы
   
}
 

void loop() {
  while((ADCSRA & (1 << ADIF)) == 0);
   u = (ADCL|ADCH << 8);

 if(u>50 && u<150){input=0;delay(200);}  
 if(u>150 && u<300){input=1;delay(200);}  
 if(u>300 && u<400){input=2;delay(200);}
 if(u>400 && u<600){input=3;delay(200);}  

  

 switch(input){
  case 0: PORTB = 0b0001; break;
  case 1: PORTB = 0b0010; break;
  case 2: PORTB = 0b0100; break;
  case 3: PORTB = 0b1000; break;
  }        
}

58 (2024-01-17 04:54:53 отредактировано Karl2233)

Re: attiny13

Класс!
Спасибо Александр!
Всё как надо.
Йо-хо-хо и бутылка рома!

59

Re: attiny13

liman324 пишет:

Попробуйте этот код:

Вопрос: Александр, как добавить сохранение нажатой кнопки в памяти?
Что б при выключении питания включалась последняя нажатая кнопка(в моем случае это вход УМ).

60

Re: attiny13

Я в железе не проверял, но должно работать

Добавлены функции для работы с EEPROM. Сохранение и считывание переменной input.

unsigned int u;
byte input;
bool w;

void setup() {
 /// конфигурация АЦП 
   ADMUX |= (1<<MUX1);// ADC2 (PB4) input
   ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIF);
   ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);// Division Factor 128
 ///
   DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3);// пины PB0-PB3 как выходы
   input=EEPROM_read(0);
}
 

void loop() {
  while((ADCSRA & (1 << ADIF)) == 0);
   u = (ADCL|ADCH << 8);

 if(u>50 && u<150){input=0;delay(200);w=1;}  
 if(u>150 && u<300){input=1;delay(200);w=1;}  
 if(u>300 && u<400){input=2;delay(200);w=1;}
 if(u>400 && u<600){input=3;delay(200);w=1;}  

 if(w==1){w=0;EEPROM_write(0,input);}

 switch(input){
  case 0: PORTB = 0b0001; break;
  case 1: PORTB = 0b0010; break;
  case 2: PORTB = 0b0100; break;
  case 3: PORTB = 0b1000; break;
  }        
}

unsigned char EEPROM_read(unsigned int uiAddress){
  while(EECR & (1<<EEPE));  // проверка готовности EEPROM 
    EEAR = uiAddress; // регистр адреса
    EECR |= (1<<EERE);// чтение EEPROM
    return EEDR; // вывод значения
}
 
void EEPROM_write(unsigned int uiAddress, unsigned char ucData){
  while(EECR & (1<<EEPE)); // проверка готовности EEPROM 
      EEAR = uiAddress; // регистр адреса
      EEDR = ucData; // регистр данных 
      EECR |= (1<<EEMPE);// Разрешение записи в EEPROM
      EECR |= (1<<EEPE); // Запись в EEPROM
} 

61

Re: attiny13

странно... запоминает только один выход - РВ2

62

Re: attiny13

unsigned int u;
byte input;
bool w;

void setup() {
 /// конфигурация АЦП 
   ADMUX |= (1<<MUX1);// ADC2 (PB4) input
   ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADIF);
   ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);// Division Factor 128
 ///
   DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3);// пины PB0-PB3 как выходы
   input=EEPROM_read(0);
}
 

void loop() {
  while((ADCSRA & (1 << ADIF)) == 0);
   u = (ADCL|ADCH << 8);

 if(u>50 && u<150){input=0;delay(200);w=1;}  
 if(u>150 && u<300){input=1;delay(200);w=1;}  
 if(u>300 && u<400){input=2;delay(200);w=1;}
 if(u>400 && u<600){input=3;delay(200);w=1;}  

 if(w==1){w=0;EEPROM_write(0,input);}

 switch(input){
  case 0: PORTB = 0b0001; break;
  case 1: PORTB = 0b0010; break;
  case 2: PORTB = 0b0100; break;
  case 3: PORTB = 0b1000; break;
  }        
}

unsigned char EEPROM_read(unsigned char ucAddress){
  while(EECR & (1<<EEPE));
  EEARL = ucAddress;
  EECR |= (1<<EERE);
  return EEDR;
}
 
void EEPROM_write(unsigned char ucAddress, unsigned char ucData){
  while(EECR & (1<<EEPE));
  EECR = (0<<EEPM1)|(0>>EEPM0);
  EEARL = ucAddress;
  EEDR = ucData;
  EECR |= (1<<EEMPE);
  EECR |= (1<<EEPE);
}

63

Re: attiny13

не запоминает, всё время на РВ2 включается.
ну да ладно, это как раз вход  AUX.
Спасибо Александр!

64

Re: attiny13

Прочитал в одной статье. "Есть ещё ножка сброса, которую можно использовать как порт ввода-вывода. Но воспользоваться ней оказалось сложней, чем я думал. Поэтому для себя оставлю «на потом». Но есть интересная особенность, о которой не все знают. На эту же ножку выведен аналоговый вход ADC0, и он работает! Правда, при напряжении на нём менее 1/4 от напряжения питания МК переходит в режим сброса. Зато от 1/4 и до напряжения питания вполне можно измерять напряжение на входе." 
Можно будет как нибудь попробовать. smile

65 (2024-11-11 18:57:17 отредактировано Karl2233)

Re: attiny13

Уважаемый Александр!
На сколько интересно создать трехканальный вольтметр на Attiny13 с выводом на OLED 1,3.
Диапазон 4-15В.
Смысл вот в чём: ставлю ИБП для питания роутера+модема+регистратора видекокамер.
А там зоопарк с напряжениями: 5-9-12.
Придется ставить DCDC  на каждое напряжение(ну или минимум на два).
Хотелось бы по нажатию кнопки видеть эти напряжения.
Понятно, можно мониторить 12 на аккумуляторе, но каждое из трёх было бы лучше.
В идеале - все четыре, но тогда придется использовать Reset как порт или без кнопки(что не смертельно, можно просто питание МК включать).
Мне когда-то попадалось такое, но сейчас не смог найти.
Конечно, если б использовать Atmega8 или 328(lgt8f328p) то захочется ещё и ток видеть...

66

Re: attiny13

На сколько интересно создать трехканальный вольтметр на Attiny13 с выводом на OLED 1,3.

В Attiny13 очень мало памяти, OLED 1,3 запустить будет очень проблематично, тем более еще три аналоговых входа надо запустить.  Attiny13 однозначно для этих целей не подойдет.

67 (2024-11-12 19:25:05 отредактировано Karl2233)

Re: attiny13

А если LGT8F328P?
Четыре вольтметра(батарея +  выходы 5+9+12В),  три амперметра (только на выходы).
Диапазон вольметров 4-15В.
Автогашение OLED  через 10-20сек. Включение по нажатию кнопки.
Это что б OLED не выгорал и не кушал аккум когда автономное питание будет.
Такое возможно?
Питание я организую от отдельного ИИП и лития 4,2В.

Можно конечно воткнуть управление кулером (DS18B20) - что б летом обдувать зарядное, всё-таки там 3-3,5А будет гулять.
Это было б уже совсем круто.

68

Re: attiny13

4 -е вольтметра это просто, а на LGT8F328P еще и точнее (12 бит) чем на ардуино.
Три амперметра, тут есть вопросы, какой диапазон, какие шунты будут использованы, если использовать напрямую входы АЦП LGT8F328P, то при небольшом падении напряжения на шунтах измерение будет не точным , лучше использовать LM358 3 шт или 1 шт LM324, тогда измерение тока будет точным при незначительном падении напряжения на шунте.

69 (2024-11-13 04:53:45 отредактировано Karl2233)

Re: attiny13

Да, операционнники использовать будет правильнее и технологичнее.

Диапазон тока: 0.00-2.00, шунт  0,01.

Думаю проще будет  поставить подстроечники и ими подгонять показания по месту. Как думаете?

Про температуру - ШИМ управление:
1. <40С =0%
2. >40С - 50%
3. >55С - 80%
4. >=70 - 100%

70

Re: attiny13

На выходных напишу скетч

71

Re: attiny13

Спасибо! С меня ром.
Так понимаю, это надо будет в отдельную ветку или статью оформить? Это ж уже отдельное устройство и не на Attiny13...

З. Ы. Что подумал... А ведь это будет почти готовый В-А метр для двухполярного БП.
Ведь один канал (В+А) может измерять минусовое плечо. Для этого надо будет ОУ немного иначе включить.

72

Re: attiny13

http://forum.rcl-radio.ru/uploads/images/2024/11/61469e83fd3a3f85cd480ef276d4f4d6.png

#define PWM_OUT    3
#define DS18B20    7
#define OLED_OK    4

PWM_OUT - выход ШИМ
DS18B20 - вход датчика температуры
OLED_OK - кнопка ативации дисплея (нажатие на кнопку = GND, кнопка без резисторов)

#define OLED_TIME_OFF 20000

OLED_TIME_OFF время работы дисплея после нажатия кнопки в мс

#define I_1       A0
#define U_1       A1
#define I_2       A2
#define U_2       A3
#define I_3       A6
#define U_3       A7

это входы измерения напряжения и тока
Измерение тока при помощи шунта и ОУ, при максимальном токе на выходе ОУ не должно превышать 5 В, тоже и для напряжение, после делителя напряжения максимальное напряжение не более 5 В


#define U1K     250.0
#define A1K     2000.0

#define U2K     250.0
#define A2K     2000.0

#define U3K     250.0
#define A3K     2000.0

Это коэффициенты для измерения тока и напряжения по 3-м каналам.

#define PWM_OUT    3
#define DS18B20    7
#define OLED_OK    4

#define OLED_TIME_OFF 20000

#define I_1       A0
#define U_1       A1
#define I_2       A2
#define U_2       A3
#define I_3       A6
#define U_3       A7

#define U1K     250.0
#define A1K     2000.0

#define U2K     250.0
#define A2K     2000.0

#define U3K     250.0
#define A3K     2000.0

#include <Wire.h> 
#include <EEPROM.h>
#include <U8glib.h>   // https://github.com/olikraus/u8glib/
#include <OneWire.h>        // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip

OneWire  ds(DS18B20); // Вход датчика 18b20
// U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);// OLED_1.3
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);// OLED_0.96

float temper;
int pwm,n_1,n_2,n_3;
int m_1,m_2,m_3;
long u_sum_1,u_sum_2,u_sum_3,i_sum_1,i_sum_2,i_sum_3;
float u_iz_1,u_iz_2,u_iz_3,i_iz_1,i_iz_2,i_iz_3;
float i_dig_1,i_dig_2,i_dig_3,u_dig_1,u_dig_2,u_dig_3;
unsigned long times,times_oled;
bool w=1;


void setup() {
  Wire.begin();Serial.begin(9600);
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}
  analogReadResolution(12);// АЦП 12 БИТ
  pinMode(A0,INPUT); // Изм.I_1
  pinMode(A1,INPUT); // Изм.U_1
  pinMode(A2,INPUT); // Изм.I_2
  pinMode(A3,INPUT); // Изм.U_2
  pinMode(A6,INPUT); // Изм.I_3
  pinMode(A7,INPUT); // Изм.U_3
  pinMode(PWM_OUT, OUTPUT);// out PWM
  pinMode(OLED_OK,INPUT_PULLUP);   // КНОПКА 
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont12r); 
  u8g.drawStr(40,15,"LGT8F328");
  u8g.drawStr(15,35,"U 0-15V | I 0-2A");
  u8g.drawStr(30,55,"rcl-radio.ru");
  } while( u8g.nextPage() );
  delay(2000);
}

void loop() {
  if(digitalRead(OLED_OK)==LOW){times_oled=millis();delay(200);}
  
  /// DS18B20 + PWM ///////////////////////////////////////////
  if(millis()-times>3000){temper = dsRead(0);times=millis();Serial.println(temper);delay(100);}
  if(temper<40){analogWrite(PWM_OUT, 0);pwm=0;}
  if(temper>=40&&temper<55){analogWrite(PWM_OUT, 127);pwm=50;}
  if(temper>=55&&temper<70){analogWrite(PWM_OUT, 204);pwm=80;}
  if(temper>=70){analogWrite(PWM_OUT, 255);pwm=100;}
  /////////////////////////////////////////////////////////////
  
  /// I ///////////////////////////////////////////////////////
  i_dig_1 = analogRead(I_1);
  i_sum_1 = i_sum_1+i_dig_1;
  n_1++;if(n_1>9){n_1=0;i_iz_1=i_sum_1/10;i_sum_1=0;} 

  i_dig_2 = analogRead(I_2);
  i_sum_2 = i_sum_2+i_dig_2;
  n_2++;if(n_2>9){n_2=0;i_iz_2=i_sum_2/10;i_sum_2=0;}

  i_dig_3 = analogRead(I_3);
  i_sum_3 = i_sum_3+i_dig_3;
  n_3++;if(n_3>9){n_3=0;i_iz_3=i_sum_3/10;i_sum_3=0;}
  /////////////////////////////////////////////////////////////

  /// U ///////////////////////////////////////////////////////
  u_dig_1 = analogRead(U_1);
  u_sum_1 = u_sum_1+u_dig_1;
  m_1++;if(m_1>9){m_1=0;u_iz_1=u_sum_1/10;u_sum_1=0;}

  u_dig_2 = analogRead(U_2);
  u_sum_2 = u_sum_2+u_dig_2;
  m_2++;if(m_2>9){m_2=0;u_iz_2=u_sum_2/10;u_sum_2=0;}

  u_dig_3 = analogRead(U_3);
  u_sum_3 = u_sum_3+u_dig_3;
  m_3++;if(m_3>9){m_3=0;u_iz_3=u_sum_3/10;u_sum_3=0;w=1;}
  /////////////////////////////////////////////////////////////

  /// OLED ////////////////////////////////////////////////////
  if(w==1&&millis()-times_oled<OLED_TIME_OFF){w=0;
  u8g.firstPage();  
   do {
  u8g.drawStr(0,10,"U ");u8g.setPrintPos(25, 10);u8g.print(u_iz_1/U1K,1);u8g.drawStr(50,10,"V");
  u8g.drawStr(70,10,"I ");u8g.setPrintPos(85, 10);u8g.print(i_iz_1/A1K,2);u8g.drawStr(115,10,"A");

  u8g.drawStr(0,25,"U ");u8g.setPrintPos(25, 25);u8g.print(u_iz_2/U2K,1);u8g.drawStr(50,25,"V");
  u8g.drawStr(70,25,"I ");u8g.setPrintPos(85, 25);u8g.print(i_iz_2/A2K,2);u8g.drawStr(115,25,"A");

  u8g.drawStr(0,40,"U ");u8g.setPrintPos(25, 40);u8g.print(u_iz_3/U3K,1);u8g.drawStr(50,40,"V");
  u8g.drawStr(70,40,"I ");u8g.setPrintPos(85, 40);u8g.print(i_iz_3/A3K,2);u8g.drawStr(115,40,"A");


  u8g.drawLine(0, 48, 128, 48);
  u8g.drawStr(0,64,"T = ");u8g.setPrintPos(25, 64);u8g.print(temper,1);u8g.drawStr(50,64,"*C");
  u8g.drawStr(70,64,"PWM =");u8g.setPrintPos(105, 64);u8g.print(pwm);
  } while( u8g.nextPage() );
  }
  if(millis()-times_oled>=OLED_TIME_OFF){u8g.firstPage();do {} while( u8g.nextPage() );}

  delay(10);
}

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}

73 (2024-11-16 16:43:11 отредактировано Karl2233)

Re: attiny13

Класс!
Ща плату разведу и залью.
Это ж скетч для lgt8f328p, верно?

Так понимаю, тут 1,3 дисплей?
А можно 0,96 дисплей и температуру в верхнюю строку?
Есть пара двухцветных, было б красиво...

74

Re: attiny13

Так понимаю, тут 1,3 дисплей?

Какую строку раскомментируете такой и будет дисплей

// U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);// OLED_1.3
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);// OLED_0.96


Это ж скетч для lgt8f328p, верно?

Только для lgt8f328p

75

Re: attiny13

температуру в верхнюю строку

#define PWM_OUT    3
#define DS18B20    7
#define OLED_OK    4

#define OLED_TIME_OFF 20000

#define I_1       A0
#define U_1       A1
#define I_2       A2
#define U_2       A3
#define I_3       A6
#define U_3       A7

#define U1K     250.0
#define A1K     2000.0

#define U2K     250.0
#define A2K     2000.0

#define U3K     250.0
#define A3K     2000.0

#include <Wire.h> 
#include <EEPROM.h>
#include <U8glib.h>   // https://github.com/olikraus/u8glib/
#include <OneWire.h>        // http://rcl-radio.ru/wp-content/uploads/2018/07/OneWire.zip

OneWire  ds(DS18B20); // Вход датчика 18b20
// U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);// OLED_1.3
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);// OLED_0.96

float temper;
int pwm,n_1,n_2,n_3;
int m_1,m_2,m_3;
long u_sum_1,u_sum_2,u_sum_3,i_sum_1,i_sum_2,i_sum_3;
float u_iz_1,u_iz_2,u_iz_3,i_iz_1,i_iz_2,i_iz_3;
float i_dig_1,i_dig_2,i_dig_3,u_dig_1,u_dig_2,u_dig_3;
unsigned long times,times_oled;
bool w=1;


void setup() {
  Wire.begin();Serial.begin(9600);
  if(EEPROM.read(100)!=0){for(int i=0;i<101;i++){EEPROM.update(i,0);}}
  analogReadResolution(12);// АЦП 12 БИТ
  pinMode(A0,INPUT); // Изм.I_1
  pinMode(A1,INPUT); // Изм.U_1
  pinMode(A2,INPUT); // Изм.I_2
  pinMode(A3,INPUT); // Изм.U_2
  pinMode(A6,INPUT); // Изм.I_3
  pinMode(A7,INPUT); // Изм.U_3
  pinMode(PWM_OUT, OUTPUT);// out PWM
  pinMode(OLED_OK,INPUT_PULLUP);   // КНОПКА 
  u8g.firstPage();  
   do {
  u8g.setFont(u8g_font_profont12r); 
  u8g.drawStr(40,15,"LGT8F328");
  u8g.drawStr(15,35,"U 0-15V | I 0-2A");
  u8g.drawStr(30,55,"rcl-radio.ru");
  } while( u8g.nextPage() );
  delay(2000);
}

void loop() {
  if(digitalRead(OLED_OK)==LOW){times_oled=millis();delay(200);}
  
  /// DS18B20 + PWM ///////////////////////////////////////////
  if(millis()-times>3000){temper = dsRead(0);times=millis();Serial.println(temper);delay(100);}
  if(temper<40){analogWrite(PWM_OUT, 0);pwm=0;}
  if(temper>=40&&temper<55){analogWrite(PWM_OUT, 127);pwm=50;}
  if(temper>=55&&temper<70){analogWrite(PWM_OUT, 204);pwm=80;}
  if(temper>=70){analogWrite(PWM_OUT, 255);pwm=100;}
  /////////////////////////////////////////////////////////////
  
  /// I ///////////////////////////////////////////////////////
  i_dig_1 = analogRead(I_1);
  i_sum_1 = i_sum_1+i_dig_1;
  n_1++;if(n_1>9){n_1=0;i_iz_1=i_sum_1/10;i_sum_1=0;} 

  i_dig_2 = analogRead(I_2);
  i_sum_2 = i_sum_2+i_dig_2;
  n_2++;if(n_2>9){n_2=0;i_iz_2=i_sum_2/10;i_sum_2=0;}

  i_dig_3 = analogRead(I_3);
  i_sum_3 = i_sum_3+i_dig_3;
  n_3++;if(n_3>9){n_3=0;i_iz_3=i_sum_3/10;i_sum_3=0;}
  /////////////////////////////////////////////////////////////

  /// U ///////////////////////////////////////////////////////
  u_dig_1 = analogRead(U_1);
  u_sum_1 = u_sum_1+u_dig_1;
  m_1++;if(m_1>9){m_1=0;u_iz_1=u_sum_1/10;u_sum_1=0;}

  u_dig_2 = analogRead(U_2);
  u_sum_2 = u_sum_2+u_dig_2;
  m_2++;if(m_2>9){m_2=0;u_iz_2=u_sum_2/10;u_sum_2=0;}

  u_dig_3 = analogRead(U_3);
  u_sum_3 = u_sum_3+u_dig_3;
  m_3++;if(m_3>9){m_3=0;u_iz_3=u_sum_3/10;u_sum_3=0;w=1;}
  /////////////////////////////////////////////////////////////

  /// OLED ////////////////////////////////////////////////////
  if(w==1&&millis()-times_oled<OLED_TIME_OFF){w=0;
  u8g.firstPage();  
   do {
  u8g.drawStr(0,34,"U ");u8g.setPrintPos(25, 34);u8g.print(u_iz_1/U1K,1);u8g.drawStr(50,34,"V");
  u8g.drawStr(70,34,"I ");u8g.setPrintPos(85, 34);u8g.print(i_iz_1/A1K,2);u8g.drawStr(115,34,"A");

  u8g.drawStr(0,49,"U ");u8g.setPrintPos(25, 49);u8g.print(u_iz_2/U2K,1);u8g.drawStr(50,49,"V");
  u8g.drawStr(70,49,"I ");u8g.setPrintPos(85, 49);u8g.print(i_iz_2/A2K,2);u8g.drawStr(115,49,"A");

  u8g.drawStr(0,64,"U ");u8g.setPrintPos(25, 64);u8g.print(u_iz_3/U3K,1);u8g.drawStr(50,64,"V");
  u8g.drawStr(70,64,"I ");u8g.setPrintPos(85, 64);u8g.print(i_iz_3/A3K,2);u8g.drawStr(115,64,"A");


  u8g.drawLine(0, 16, 128, 16);
  u8g.drawStr(0,10,"T = ");u8g.setPrintPos(25, 10);u8g.print(temper,1);u8g.drawStr(50,10,"*C");
  u8g.drawStr(70,10,"PWM =");u8g.setPrintPos(105, 10);u8g.print(pwm);
  } while( u8g.nextPage() );
  }
  if(millis()-times_oled>=OLED_TIME_OFF){u8g.firstPage();do {} while( u8g.nextPage() );}

  delay(10);
}

float dsRead(byte x) {
  byte data[2], addr[8][8], kol = 0;
  while (ds.search(addr[kol])) {  // поиск датчиков, определение адреса и кол-ва датчиков
    kol++;
  } 
  ds.reset_search();  // Сброс поиска датчика
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0x44, 0);  // Измерение температуры с переносом данных в память
  ds.reset();         // Инициализация, выполняется сброс шины
  ds.select(addr[x]); // Обращение к датчику по адресу
  ds.write(0xBE);     // Обращение памяти
  data[0] = ds.read();// Чтение памяти byte low
  data[1] = ds.read();// Чтение памяти byte high
  float value = ((data[1] << 8) | data[0]) / 16.0; return (float)value; // Расчет температуры и вывод
}