DAC CS8416 + CS4398 (Arduino)

ЦАП — цифро-аналоговый преобразователь — это устройство, которое преобразует информацию из цифрового вида  в аналоговые сигналы, при этом максимально точно и без искажений.

Собрать внешний ЦАП на компонентах предложных в статье не сложно, он содержит несколько недорогих компонентов и в настройке практически не нуждается. Дополнительно во внешнем ЦАПе используется плата Arduino Nano, энкодер и дисплей LCD1602(I2C). Фактически ЦАП может работать и без Arduino, но суть проекта была в получении к дополнительных функциям ЦАП на CS4398, таким как управление громкостью и функции MUTE.

Внешний ЦАП состоит из 5-х основных модулей:

  • приемник S/PDIF на CS8416
  • ЦАП на CS4398
  • фильтр-сумматор на NE5532
  • плата Arduino Nano
  • блок питания

S/PDIF (Sony/Philips Digital Interface) – распространенный и стандартизированный интерфейс, предназначенный для передачи цифрового звука между доступными компонентами, звуковыми картами, ресиверами и аудиоаппаратурой.

I2S — стандарт интерфейса электрической последовательной шины, использующийся для соединения цифровых аудиоустройств. Применяется для передачи PCM-аудиоданных между интегральными схемами в электронном устройстве. Шина I2S передает по разным линиям сигналы синхронизации и сигналы данных, что приводит к снижению фазового дрожания, типичного для систем связи, восстанавливающих сигналы синхронизации из целого потока.

Входной цифровой сигнал имеет формат S/PDIF (цифровой аудио интерфейс разработанный фирмами SONY/PHILIPS, предназначен для передачи цифрового сигнала между аудио устройствами), ЦАП CS4398 не поддерживает такой формат, для преобразования S/PDIF необходим ресивер на CS8416 который преобразует S/PDIF в цифровой сигнал в формат I2S. С выхода ЦАП звуковой сигнал поступает на фильтр-сумматор собранный на ОУ NE5532.

Для нормальной работы ресивер и ЦАП должный иметь одинаковый формат передачи цифровых данных, в данном случае это I2S 24 бит с частотой сэмплирования 192 кГц.

Основные характеристики CS4398:

  • отношение сигнал/шум 120 дБ
  • динамический диапазон 120 дБ
  • уровень гармонических искажений -107 дБ
  • взаимное проникновение каналов 120 дБ
  • входной формат: PCM I2S, RJ, LJ от 16 бит 32 кГц до 24 бит 192 кГц

В моем случае внешний ЦАП имеет упрощенное питание, для уменьшения шумов и искажений желательно применять рекомендованную схему питания (см.ниже).

Выше показана схема ресивера на CS8416, он имеет один активный вход, но можно использовать все 4-е доступные входы. Коммутация входами осуществляется при помощи пинов RSEL1 и RSEL0 микросхемы ресивера , при этом лог. 1 подается с питания VL (+5 В), а логический ноль с DGND.

INPUT RSEL0 RSEL1
RXP0 0 0
RXP1 1 0
RXP2 0 1
RXP3 1 1

Ресивер работает независимо от Arduino, в схеме присутствует индикатор режима работы светодиод D1, при подключении коаксиального кабеля с источником цифрового сигнала светодиод гаснет, при отключении кабеля загорается.

Для питания схемы ресивера используется следующая схема:

Основное напряжение +5 В подается с платы Arduino, которое является напряжением VL, для питания VD и VA используются два стабилизатора напряжения 78L33 (3.3 В).

Выше показана схема ЦАП, для его питания я использую напряжение 5 В подаваемое с платы Arduino.

Для питания фильтр-сумматора необходим отдельный двух полярный источник +/-12 В. Для настройки уровня выходного сигнала можно изменить номиналы резисторов R15 R22.

Ниже показана схема рекомендованного источника питания.

Для питания внешнего ЦАПа рекомендуется использовать три независимых источника питания, который состоит из одного трансформатора с тремя независимыми вторичными обмотками,  одна из которых имеет отвод от середины для двух полярного источника питания. Каждый источник питания имеет свой диодный мост. При этом аналоговая и цифровая земля объединяются через дроссель. Дополнительно как можно ближе к микросхемам по цепи питания устанавливаются фильтрующие конденсаторы 0,1 и 22 мкФ. Подключение к плате Arduino осуществляется тремя проводами (I2C) SDA SCL и GND к DGND цепи питания ЦАП.

Как было отмечено ранее, управление ЦАП CS4398 при помощи Arduino позволяет управлять громкостью и режимом MUTE. Регулировка громкостью и режимом MUTE осуществляется при помощи энкодера (KY-040), информация выводится на дисплей LCD1602 работающего на шине I2C. Регулировка громкости содержит 130 ступеней (по 0,5 дБ), при нажатии кнопки энкодера можно включить или выключить режим MUTE.

 

#include <Wire.h>
#include <EEPROM.h>
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {7,7,7,7,7,7,7,7};
      byte v2[8] = {7,7,0, 0, 0, 0, 0, 0};      
      byte v3[8] = { 0, 0, 0, 0, 0,0,31,31};
      byte v4[8] = {31,31, 0, 0, 0, 0,31,31};
      byte v5[8] = { 28, 28, 0, 0, 0, 0, 28, 28};//
      byte v6[8] = {28,28,28,28,28,28,28,28};
      byte v7[8] = { 0, 0, 0, 0, 0, 0,7,7};
      byte v8[8] = { 31, 31,0,0,0,0,0, 0};
      int a[3];
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
 unsigned long time,oldPosition  = -999,newPosition;
 int vol,vol_d;
 bool w,mute;

void setup() {
 Wire.begin();
 lcd.init();lcd.backlight();
 pinMode(10,INPUT);
 lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);
 lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);
 lcd.createChar(7, v7);lcd.createChar(8, v8);
 Serial.begin(9600);
 lcd.setCursor(0,0);lcd.print("     CS4398     ");
 lcd.setCursor(0,1);lcd.print("     CS8416     ");
 MsTimer2::set(1, to_Timer);MsTimer2::start();
 delay(1000);
 vol = EEPROM.read(0);
 wireWrite(0x4C, 0x02, 0b00011010);// I2S 24 bit / 48 kHz / 100...200 kHz
 wireWrite(0x4C, 0x03, 0b00001001);// default
 wireWrite(0x4C, 0x04, 0b11000000);// default
 wireWrite(0x4C, 0x05, vol);
 wireWrite(0x4C, 0x06, vol);
 wireWrite(0x4C, 0x07, 0b10110000);// default
 wireWrite(0x4C, 0x08, 0b01000000);// default
 wireWrite(0x4C, 0x09, 0b00001000);// default
 Serial.print("Chip ID 0");
 Serial.println(wireRead(0x4C, 0x01),BIN);
 lcd.clear();
}

void loop() {
 if(digitalRead(10)==LOW && mute==0){mute=1;wireWrite(0x4C, 0x04, 0b11011000);delay(300);} 
 if(digitalRead(10)==LOW && mute==1){mute=0;wireWrite(0x4C, 0x04, 0b11000000);delay(300);} 
 if(mute==1){lcd.setCursor(0,1);lcd.print("MUTE");}else{lcd.setCursor(0,1);lcd.print("192k");}
 
 if (newPosition != oldPosition){oldPosition = newPosition;
     vol=vol+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(vol<0){vol=0;}if(vol>130){vol=130;}
      wireWrite(0x4C, 0x05, vol);
      wireWrite(0x4C, 0x06, vol);
      lcd.setCursor(0,0);lcd.print("VOLUME ");
     }
      
     vol_d=130-vol;
     a[0]=vol_d/100;
     a[1]=vol_d/10%10;
     a[2]=vol_d%10;
      for(i=0;i<3;i++){
      switch(i){
        case 0: e1=7,e2=8,e3=9;break;
        case 1: e1=10,e2=11,e3=12;break;
        case 2: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }

 delay(20);if(millis()-time>5000 && w==1){w=0;EEPROM.write(0,vol);}
 }// loop
 

void wireWrite(byte addr, byte reg, byte data){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.write (data);
  Wire.endTransmission();
  }

byte wireRead(int addr, int reg){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

Если открыть монитор порта Вы увидите ID номер CS4398:

This register is Read-Only. Bits 7 through 3 are the part number ID, which is 01110b (14h), and the remaining Bits (2 through 0) are for the chip revision (Rev. A = 000, Rev. B = 001, …)

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=202


Селектор входов

 

Изменив немного схему, добавив два резистора 4,7 кОм к пинам TSEL1 и TSEL0 CS8416, можно сделать селектор входов. Коммутация входов осуществляется при помощи Arduino (выходы A0 A1). Добавлена одна кнопка для переключения входов которая подключена к пину D2 Arduino (кнопка при нажатии замыкается на GND).

Уровень громкости и номер выбранного входа сохраняется в энергонезависимой памяти.

#include <Wire.h>
#include <EEPROM.h>
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {7,7,7,7,7,7,7,7};
      byte v2[8] = {7,7,0, 0, 0, 0, 0, 0};      
      byte v3[8] = { 0, 0, 0, 0, 0,0,31,31};
      byte v4[8] = {31,31, 0, 0, 0, 0,31,31};
      byte v5[8] = { 28, 28, 0, 0, 0, 0, 28, 28};//
      byte v6[8] = {28,28,28,28,28,28,28,28};
      byte v7[8] = { 0, 0, 0, 0, 0, 0,7,7};
      byte v8[8] = { 31, 31,0,0,0,0,0, 0};
      int a[3];
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
 unsigned long time,oldPosition  = -999,newPosition;
 int vol,vol_d,in;
 bool w,mute;

void setup() {
 Wire.begin();
 lcd.init();lcd.backlight();
 pinMode(10,INPUT);   // кнопка энкодера
 pinMode(A0,OUTPUT);  // RSEL1
 pinMode(A1,OUTPUT);  // RSEL0
 pinMode(2,INPUT_PULLUP); // кнопка IN
 lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);
 lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);
 lcd.createChar(7, v7);lcd.createChar(8, v8);
 Serial.begin(9600);
 lcd.setCursor(0,0);lcd.print("     CS4398     ");
 lcd.setCursor(0,1);lcd.print("     CS8416     ");
 MsTimer2::set(1, to_Timer);MsTimer2::start();
 delay(1000);
 vol = EEPROM.read(0);
 in = EEPROM.read(1);
 wireWrite(0x4C, 0x02, 0b00011010);// I2S 24 bit / 48 kHz / 100...200 kHz
 wireWrite(0x4C, 0x03, 0b00001001);// default
 wireWrite(0x4C, 0x04, 0b11100000);// default
 wireWrite(0x4C, 0x05, vol);
 wireWrite(0x4C, 0x06, vol);
 wireWrite(0x4C, 0x07, 0b10110000);// default
 wireWrite(0x4C, 0x08, 0b01000000);// default
 wireWrite(0x4C, 0x09, 0b00001000);// default
 Serial.print("Chip ID 0");
 Serial.println(wireRead(0x4C, 0x01),BIN);
 lcd.clear();
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }
}

void loop() {
 if(digitalRead(2)==LOW){in++;if(in>2){in=0;}lcd.clear();time=millis();w=1;
 lcd.setCursor(5,0);lcd.print("INPUT");lcd.setCursor(05,1);
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }delay(2000);lcd.clear();}
 
  
 if(digitalRead(10)==LOW && mute==0){mute=1;wireWrite(0x4C, 0x04, 0b11011000);delay(300);} 
 if(digitalRead(10)==LOW && mute==1){mute=0;wireWrite(0x4C, 0x04, 0b11000000);delay(300);} 
 if(mute==1){lcd.setCursor(0,1);lcd.print("MUTE  ");}
 else{lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in+1);
 }
 
 if (newPosition != oldPosition){oldPosition = newPosition;
     vol=vol+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(vol<0){vol=0;}if(vol>130){vol=130;}
      wireWrite(0x4C, 0x05, vol);
      wireWrite(0x4C, 0x06, vol);}
    lcd.setCursor(0,0);lcd.print("VOLUME ");
     vol_d=130-vol;
     a[0]=vol_d/100;
     a[1]=vol_d/10%10;
     a[2]=vol_d%10;
      for(i=0;i<3;i++){
      switch(i){
        case 0: e1=7,e2=8,e3=9;break;
        case 1: e1=10,e2=11,e3=12;break;
        case 2: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }

 delay(20);if(millis()-time>5000 && w==1){w=0;EEPROM.write(0,vol);EEPROM.write(1,in);}
 }// loop
 

void wireWrite(byte addr, byte reg, byte data){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.write (data);
  Wire.endTransmission();
  }

byte wireRead(int addr, int reg){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

Добавлен баланс, изменено подключение

 

#include <Wire.h>
#include <EEPROM.h>
#include <MsTimer2.h> // http://rcl-radio.ru/wp-content/uploads/2018/11/MsTimer2.zip
#include <Encoder.h>  // http://rcl-radio.ru/wp-content/uploads/2019/05/Encoder.zip
#include <LiquidCrystal_I2C.h> //Библиотека -  http://forum.rcl-radio.ru/misc.php?action=pan_download&item=45&download=1
 LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей 
 Encoder myEnc(9, 8);//CLK, DT
      byte v1[8] = {7,7,7,7,7,7,7,7};
      byte v2[8] = {7,7,0, 0, 0, 0, 0, 0};      
      byte v3[8] = { 0, 0, 0, 0, 0,0,31,31};
      byte v4[8] = {31,31, 0, 0, 0, 0,31,31};
      byte v5[8] = { 28, 28, 0, 0, 0, 0, 28, 28};//
      byte v6[8] = {28,28,28,28,28,28,28,28};
      byte v7[8] = { 0, 0, 0, 0, 0, 0,7,7};
      byte v8[8] = { 31, 31,0,0,0,0,0, 0};
      int a[3];
      byte i,d1,d2,d3,d4,d5,d6,e1,e2,e3;
 unsigned long time,oldPosition  = -999,newPosition;
 int vol,vol_d,in,balanc,balanc_d,menu;
 bool w,mute;

void setup() {
 Wire.begin();
 lcd.init();lcd.backlight();
 pinMode(10,INPUT);   // кнопка энкодера
 pinMode(A0,OUTPUT);  // RSEL1
 pinMode(A1,OUTPUT);  // RSEL0
 pinMode(2,INPUT_PULLUP); // кнопка IN
 pinMode(3,INPUT_PULLUP); // кнопка MUTE
 lcd.createChar(1, v1);lcd.createChar(2, v2);lcd.createChar(3, v3);
 lcd.createChar(4, v4);lcd.createChar(5, v5);lcd.createChar(6, v6);
 lcd.createChar(7, v7);lcd.createChar(8, v8);
 Serial.begin(9600);
 lcd.setCursor(0,0);lcd.print("     CS4398     ");
 lcd.setCursor(0,1);lcd.print("     CS8416     ");
 MsTimer2::set(1, to_Timer);MsTimer2::start();
 delay(1000);
 vol = EEPROM.read(0);in = EEPROM.read(1);balanc = EEPROM.read(2)-20;
 wireWrite(0x4C, 0x02, 0b00011010);// I2S 24 bit / 48 kHz / 100...200 kHz
 wireWrite(0x4C, 0x03, 0b00001001);// default
 wireWrite(0x4C, 0x04, 0b11100000);// default
 wireWrite(0x4C, 0x05, vol+balanc+20);
 wireWrite(0x4C, 0x06, vol-balanc+20);
 wireWrite(0x4C, 0x07, 0b10110000);// default
 wireWrite(0x4C, 0x08, 0b01000000);// default
 wireWrite(0x4C, 0x09, 0b00001000);// default
 Serial.print("Chip ID 0");
 Serial.println(wireRead(0x4C, 0x01),BIN);
 lcd.clear();
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }
}

void loop() {
 /// MENU /////////////////////////////////////// 
 if(digitalRead(10)==LOW){menu++;if(menu>1){menu=0;}lcd.clear();time=millis();w=1;delay(200);}
  
 /// INPUT ////////////////////////////////////// 
 if(digitalRead(2)==LOW){in++;if(in>2){in=0;}lcd.clear();time=millis();w=1;
 lcd.setCursor(5,0);lcd.print("INPUT");lcd.setCursor(5,1);
 switch(in){
 case 0: digitalWrite(A0, LOW);digitalWrite(A1, LOW);lcd.print("COAX 1");break;// px0 
 case 1: digitalWrite(A0, LOW);digitalWrite(A1, HIGH);lcd.print("COAX 2");break;// px1
 case 2: digitalWrite(A0, HIGH);digitalWrite(A1, LOW);lcd.print("COAX 3");break;// px2
 }delay(1000);lcd.clear();}
 
 /// MUTE /////////////////////////////
 if(digitalRead(3)==LOW && mute==0){mute=1;wireWrite(0x4C, 0x04, 0b11011000);delay(300);} 
 if(digitalRead(3)==LOW && mute==1){mute=0;wireWrite(0x4C, 0x04, 0b11000000);delay(300);} 
 if(mute==1){lcd.setCursor(0,1);lcd.print("MUTE  ");}
 else{lcd.setCursor(0,1);lcd.print("COAX ");lcd.print(in+1);
 }
 
 /// VOLUME + BALANCE ////////////////
 if(menu==0){
 if (newPosition != oldPosition){oldPosition = newPosition;
     vol=vol+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(vol<0){vol=0;}if(vol>150){vol=150;}
      wireWrite(0x4C, 0x05, vol+balanc+20);
      wireWrite(0x4C, 0x06, vol-balanc+20);}
      lcd.setCursor(0,0);lcd.print("VOLUME ");
     vol_d=150-vol;
     a[0]=vol_d/100;
     a[1]=vol_d/10%10;
     a[2]=vol_d%10;

 }

 if(menu==1){
 if (newPosition != oldPosition){oldPosition = newPosition;
     balanc=balanc+newPosition;myEnc.write(0);newPosition=0;time=millis();w=1;
      if(balanc<-20){balanc=-20;}if(balanc>20){balanc=20;}
      wireWrite(0x4C, 0x05, vol+balanc+20);
      wireWrite(0x4C, 0x06, vol-balanc+20);}
      lcd.setCursor(0,0);lcd.print("BALANCE ");
     if(balanc<0){lcd.setCursor(9,0);lcd.write((uint8_t)3);}else{lcd.setCursor(9,0);lcd.print(" ");}
     balanc_d=abs(balanc);
     a[0]=balanc_d/10;
     a[1]=balanc_d%10;
 }
  //////////////////////////////////  
    if(menu==0){
      for(i=0;i<3;i++){
      switch(i){
        case 0: e1=7,e2=8,e3=9;break;
        case 1: e1=10,e2=11,e3=12;break;
        case 2: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}
///////////////////////////////////////
if(menu==1){
       for(i=0;i<2;i++){
      switch(i){
        case 0: e1=10,e2=11,e3=12;break;
        case 1: e1=13,e2=14,e3=15;break;
        }
      switch(a[i]){
        case 0: d1=1,d2=8,d3=6,d4=1,d5=3,d6=6;break;
        case 1: d1=32,d2=2,d3=6,d4=32,d5=32,d6=6;break;
        case 2: d1=2,d2=8,d3=6,d4=1,d5=4,d6=5;break;
        case 3: d1=2,d2=4,d3=6,d4=7,d5=3,d6=6;break;
        case 4: d1=1,d2=3,d3=6,d4=32,d5=32,d6=6;break;
        case 5: d1=1,d2=4,d3=5,d4=7,d5=3,d6=6;break;
        case 6: d1=1,d2=4,d3=5,d4=1,d5=3,d6=6;break;
        case 7: d1=1,d2=8,d3=6,d4=32,d5=32,d6=6;break;
        case 8: d1=1,d2=4,d3=6,d4=1,d5=3,d6=6;break;
        case 9: d1=1,d2=4,d3=6,d4=7,d5=3,d6=6;break;
    }
     
      lcd.setCursor(e1,0);lcd.write((uint8_t)d1);lcd.setCursor(e2,0);lcd.write((uint8_t)d2);lcd.setCursor(e3,0);lcd.write((uint8_t)d3);
      lcd.setCursor(e1,1);lcd.write((uint8_t)d4);lcd.setCursor(e2,1);lcd.write((uint8_t)d5);lcd.setCursor(e3,1);lcd.write((uint8_t)d6);
 }}


 delay(20);if(millis()-time>10000 && w==1){w=0;EEPROM.write(0,vol);EEPROM.write(1,in);EEPROM.write(2,balanc+20);
 menu=0;}
 }// loop
 
void wireWrite(byte addr, byte reg, byte data){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.write (data);
  Wire.endTransmission();
  }

byte wireRead(int addr, int reg){
  Wire.beginTransmission(addr);
  Wire.write (reg);
  Wire.endTransmission();
  Wire.requestFrom(addr,1);
  while(Wire.available()<1);
  byte value = Wire.read();
  return value;
  }  

void to_Timer(){newPosition = myEnc.read()/4;}  

Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=2306#p2306

Добавить комментарий

Войти с помощью: