Вопрос новичка про arduino mega 2560 и сегментный дисплей shd0032 со сдвиговым регистром

gifrom
Offline
Зарегистрирован: 13.08.2015

Недавно приобрёл плату, хочу попытаться смастерить спидометр. И был у меня дисплей shd0032 http://lib.chipdip.ru/042/DOC001042790.pdf . Два дня начитывался статей вроде "Подключение LCD к Arduino через сдвиговый регистр 74HC595" и перекапывал интернет. Дисплей заработал по этой схеме http://forum.homedistiller.ru/index.php?topic=106725.400 , но я никак не могу понять как вывести на дисплей желаемое число, пытался из кода в статье выдернуть всё что касается дисплея, но ничего не получилось. Может кому попадались статьи по подключению таких дисплеев, может для него какие библиотеки есть.

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

все просто: вам нужно знать соотвесвие битов(0..7) сегментам(a...g) вот пример для SPI - SCK(строб) и MOSI(данные):

#define NUM 4 //число цифр
#define LATCH 5 // пин регистра

const byte font[21] =      //seven segment digits in bits
{  
//PGFEDCBA сегменты
 B11000000, //0 
 B11111001, //1  
 B10100100, //2  
 B10110000, //3  
 B10011001, //4  
 B10010010, //5  
 B10000010, //6  
 B11111000, //7  
 B10000000, //8  
 B10010000, //9
 0xFF,      //space
 B10111111, //-
 B11110111, //_ 
 B10001000, //A
 B10000011, //b
 B11000110, //C
 B10100001, //d
 B10000110, //E
 B10001110, //F
 B11000010, //G
 B10001001  //H
};
byte digit(char c){
  switch(c){
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      return font[c - '0'];
    case '-':
      return font[11];
    case '_':
      return font[12];
    case 'A':
    case 'a':
      return font[13];
    case 'B':
    case 'b':
      return font[14];
    case 'C':
    case 'c':
      return font[15];
    case 'D':
    case 'd':
      return font[16];
    case 'E':
    case 'e':
      return font[17];
    case 'F':
    case 'f':
      return font[18];
    case 'G':
    case 'g':
      return font[19];
    case 'H':
    case 'h':
      return font[20];
    case ' ':
    default:
      return font[10];
  }  
}
void Display(const char* str, int len){
  for(int i=len;i>=0;i--){
    SPI.transfer(digit(str[i]));
  }
  for(int i=len;i<NUM;i++){
    SPI.transfer(digit(' '));
  }
  digitalWrite(LATCH, LOW);
  digitalWrite(LATCH, HIGH); 
}

Только сам код вывода. Использование: Display("1234",4);

gifrom
Offline
Зарегистрирован: 13.08.2015

Нашёл другой  пример кода с этим дисплеем, но сколько не пытался понять и выдернуть необходимый код, покуда ничего не вышло, вечные ошибки

// Детектор нуля идет на 0-е прерывание (pin 2)
// Прерывание от валкодера (B pin валкодера) на 1 прерывание (pin 3)
// Второй пин валкодера (A) подключен к pin 4
// Управление симистором для фазового регулятора реализовано через pin 5
// Нажатие кнопки валкодера (S) подключено к pin 6 (низкий уровень при нажатии)
// Вход ENABLE SND0032 дисплея подключен на pin 7 (активный уровень низкий)
// Вход LATCH SND0032 дисплея подключен на pin 8
// Вход CLOCK SND0032 дисплея подключен на pin 9
// Вход SERIAL-IN SND0032 дисплея подключен на pin 10
// АЦП от трансформатора подключен на pin А0

#include <EEPROM.h>

#define DEBUG  // Режим отладки
#define Serial1 Serial
char m_version[]="v0.2";

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

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

#define MAX_INDEX_INPUT 255  // Выравниваем по границе байта, тк увеличиваем считывание анального входа. (было 70)
unsigned int data_adc[MAX_INDEX_INPUT+1];
unsigned int tic_adc[MAX_INDEX_INPUT+1];
volatile uint16_t deltaArray[16];      // массив для вычисления средней дельты отставания реального нуля напряжения
volatile uint8_t  deltaIndex=0;        // текущий индекс массива средней дельты отставания реального нуля напряжения
volatile uint16_t deltaZ;              // Дельта в тиках прерывания нуля и начала возрастания напряжения.
volatile unsigned int VolVal;          // Считанное с АЦП значение напряжения
volatile int MaxVolts, MaxVoltsOut;    // Пиковое напряжение
volatile unsigned char StateVolts=0;   // Состояние вычисление среднеквадратичного 
//0 - надо вычислить - запускается старт, 1 - вычисляется, 2 - вычислено, 3 - идет обработка рузультата
// 4 - Результат обработан, можно вычислять следующий
unsigned int ticIndex=0;            // Текущий индекс массива дла расчета среднеквадратичного

// Serial
#define RX_BUFFER_SIZE 70
#define TX_BUFFER_SIZE 70
char tbuffer[TX_BUFFER_SIZE];
char FlUsart=0; // Признак того, что надо вывести информацию на СОМ-порт
char RBuffer[RX_BUFFER_SIZE];
int PosRx = 0;


#define PIN_TRIAC  5    // Управление симистором реализовано через PIN 5
#define PIN_VOLC_B 4    // Определение пина B валкодера
#define PIN_VOLC_S 6    // Определение пина S валкодера

#define D_IN         10 //Определение бита IN
#define D_CLOCK      9 //Определение бита CLOCK 
#define D_LATCH      8 //Определение бита LATCH 
#define D_ENABLE     7 //Определение бита ENABLE 
#define BYTES 4 //Количество разрядов
unsigned char chars[BYTES] ={0,0,0,0}; //Массив разрядов
#define SYMBOLS_ARRAY_LENGTH 12 //Длина массива символов
unsigned char Symbols[SYMBOLS_ARRAY_LENGTH]={ // Массив символов индикатора
    252, // 0
    96, // 1
    218, // 2
    242, // 3
    102, // 4
    182, // 5
    190, // 6
    224, // 7
    254, // 8
    246, // 9
    1, // .
    2 // - 
};
char CountKeys;       // Переменная для защиты от дребезга
char reDisplayData;   // Флаг обновления информации на дисплее/

// Переменные второго счетчика 
volatile int Counter1=0;
volatile unsigned long Sec, LSec;   // Текущее состояние времени с начала процесса (не беззнаковое, потому, что есть проверки на <0);
volatile unsigned long pChangeSec;  // Временная отметка последних изменений в параметрах
char paramChanged = 0;              // Флаг, что требуется перезаписать eeprom



unsigned long TekPower;
unsigned int OpenTriacArray[16];
unsigned int OpenTriacIndex=0;
unsigned int TimeOpenTriac=0;
unsigned int TicSqNapr; // Количество тиков таймера от нуля до нуля, на основании которого рассчитано среднеквадратичное

// Установка мощности
char         PowerEnabled = 1;  // Флаг включения нагрузки 
unsigned int Power=2000;       // Номинальная мощность ТЭНов
unsigned int UstPower=1000;     // Нужно получить мощность от регулятора (текущая мощность)

/*
 * Режимы работы
 */
#define MODE_UST_POWER   0               // Режим отображения/установки текущей мощности
#define MIN_MODE         MODE_UST_POWER  // < Минимальный режим
#define MODE_DESP_MAXU   1               // Режим отображения максимального напряжения
#define MODE_MAX_POWER   2               // Режим отображения/установки максимальной мощности
#define MAX_MODE         MODE_MAX_POWER  // < Максимальный режим

unsigned char StateMachine = MIN_MODE;


#define PR_REWRITE_EEPROM 19  // Константа, которая содержит признак необходимости перезаписи энергонезависимой памяти (1-254). 
// При запуске программы, значение 0-го байта ЕЕПРОМ сравнивается с этим знначением, 
// и если они не совпадают, тогда энергонезависимая памиять переписывается текущими значениями переменных
// То есть для перезаписи контанты при первом запуске, ее значение надо поменять
unsigned int ee_addr; // Переменная для хранения текущего адреса чтения/записи в EEPROM


unsigned char eeReadChar()
{
  unsigned char lByte = EEPROM.read(ee_addr);
  ee_addr++;
  return lByte;
}

void eeWriteChar(char p_value)
{
  if (EEPROM.read(ee_addr)!=p_value)
    EEPROM.write(ee_addr, p_value);
  ee_addr++;
}

void eeWriteInt(int p_value)
{
  unsigned char lByte = (unsigned char) (p_value);
  unsigned char hByte =(unsigned char) (p_value >> 8);

  // Для экономии ресурса памяти, сначала проверяем ее содержимое и запись производим только если значение отличается.
  eeWriteChar(lByte);
  eeWriteChar(hByte);
}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int eeReadInt()
{
  unsigned char lByte = eeReadChar();
  unsigned char hByte = eeReadChar();
  return (unsigned int) (lByte) | (unsigned int)  (hByte << 8);
}

// Сохранение всех полезных настроек в eeprom
void writeEEPROM()
{ 
  int i; 
  ee_addr=0;
  eeWriteChar(PR_REWRITE_EEPROM);  
  eeWriteInt(Power);
  eeWriteInt(UstPower);
  eeWriteChar(StateMachine);
}

// Чтение настроек из eeprom
void readEEPROM()
{
  int i; 
  ee_addr=0;
  eeReadChar();  // Пропуск первого байта
  Power=eeReadInt();
  UstPower=eeReadInt();
  StateMachine = eeReadChar();
}



//Отправить 1 байт в SERIAL_IN дисплея
void push_byte(unsigned char _byte) 
{
  unsigned char j;
  for(j=0;j<8;j++){
    digitalWrite(D_CLOCK, LOW);
    digitalWrite(D_IN, 1 & _byte);
    _byte = _byte>>1;
    digitalWrite(D_CLOCK, HIGH);    
  } 
}

//Показать текущие значения в массиве разрядов
void dispData(void)
{ 
  unsigned char i;
  unsigned char dot = (Sec & 1);
  
  switch (StateMachine) {
  case MODE_UST_POWER:
    // Режим отображения текущей мощности
    i = UstPower/1000;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[3] = Symbols[i]+dot;
    i = (UstPower%1000)/100;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[2] = Symbols[i];
    i = (UstPower%100)/10;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[1] = Symbols[i];
    i = (UstPower%10);
    if (i<SYMBOLS_ARRAY_LENGTH) chars[0] = Symbols[i];
    break;
    
   case MODE_DESP_MAXU:
    // Режим отображения максимального напряжения
    if (i<SYMBOLS_ARRAY_LENGTH) chars[3] = 16; // Это код символа нижнего подчеркивания.
    i = (MaxVoltsOut%1000)/100;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[2] = Symbols[i];
    i = (MaxVoltsOut%100)/10;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[1] = Symbols[i];
    i = (MaxVoltsOut%10);
    if (i<SYMBOLS_ARRAY_LENGTH) chars[0] = Symbols[i];
    break;
    
  case MODE_MAX_POWER:
    // Режим отображения максимальной мощности
    i = Power/1000;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[3] = Symbols[i]+dot;
    i = (Power%1000)/100;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[2] = Symbols[i]+dot;
    i = (Power%100)/10;
    if (i<SYMBOLS_ARRAY_LENGTH) chars[1] = Symbols[i]+dot;
    i = (Power%10);
    if (i<SYMBOLS_ARRAY_LENGTH) chars[0] = Symbols[i]+dot;
    break;
  }
  
  
  for (i=0;i<BYTES;i++) {
    push_byte(chars[i]);
  } 
  digitalWrite(D_LATCH, HIGH);
  digitalWrite(D_LATCH, LOW);
  reDisplayData = 0;
}

void setup() 
{
  uint8_t analog_reference = DEFAULT;
  Serial1.begin(9600);

  // Настройка ADC
  sbi(ADCSRA,ADPS2);
  cbi(ADCSRA,ADPS1);
  cbi(ADCSRA,ADPS0);
  ADMUX = (analog_reference << 6) | (0 & 0x07);
  sbi(ADCSRA,ACIE);
  sbi(ADCSRA,ADSC);
  sbi(ADCSRA,ADATE);
  
  // Читаем ранее сохраненные значения из энергонезависимой памяти.
  if (EEPROM.read(0)!=PR_REWRITE_EEPROM) { 
    writeEEPROM();
  }


  pinMode(PIN_TRIAC,OUTPUT);
  digitalWrite(PIN_TRIAC,LOW);
  
  pinMode(PIN_VOLC_B, INPUT);
  pinMode(PIN_VOLC_S, INPUT);
  digitalWrite(PIN_VOLC_S,HIGH);
  
  pinMode(D_IN, OUTPUT);
  pinMode(D_CLOCK, OUTPUT);
  pinMode(D_LATCH, OUTPUT);
  pinMode(D_ENABLE, OUTPUT);

  attachInterrupt(1, VOLC_ISR, RISING);
  attachInterrupt(0, zero_crosss_int, RISING);  // Устанавливаем на 0-е прерывание функцию (это pin 2) обработку от детектора нулюя сетевого напряжения

  // Таймер 2 используется для подсчета числа секунд и запуска расчета чреднеквадратичного напряжения на входе
  // Прерываение по этому таймеру будет вызываться 125 раз в секунду.
  TCCR2A = (1<<WGM21);    // Режим CTC (сброс по совпадению)
  TCCR2A=0x00;
  TCCR2B=0x07;       //
  TCNT2=0x00;
  OCR2A=0x7D;
  OCR2B=0x00;  
  TIMSK2 = (1<<OCIE2A);   // Разрешить прерывание по совпадению


  // Таймер 1 - управление открытием симистора 
  TCCR1A=0x00;
  TCCR1B=0x03;
  TCNT1H=0x00;
  TCNT1L=0x00;
  ICR1H=0x00;
  ICR1L=0x00;
  OCR1AH=0x00;
  OCR1AL=0x02;
  OCR1BH=0x00;
  OCR1BL=0x00;
  TIMSK1 = (1<<OCIE1A);   // Разрешить прерывание по совпадению

  readEEPROM();           // Читаем все из eeprom

  // Обновляем данные на дисплее и включаем его
  dispData();
  digitalWrite(D_ENABLE, LOW);
  
  StateVolts=0;
  sei();                 // Глобально разрешить прерывания
}


/**
 * Функция обработки прерывания от линии B валкодера
 * В зависимости от состояния линии A валкодера, определяем направление вращения.
 */
void VOLC_ISR()
{
  char v = digitalRead(PIN_VOLC_B);
  switch (StateMachine) {
  case MODE_UST_POWER:
    // Установка текущей мощности
    if (v) {
      UstPower++;
      if (UstPower > Power) UstPower=Power;
    } else {
      UstPower--;
      if (UstPower < 0) UstPower=0;
    }
    paramChanged = 1; // Отмечаем, что требуется запись в eeprom 
    pChangeSec = Sec; // Отметка времени последнего изменения
    reDisplayData++;
    break;
  case MODE_MAX_POWER:
    // Установка максимальной мощности
    if (v) {
      Power++;
      if (UstPower > Power) UstPower=Power;
    } else {
      Power--;
      if (Power < 0) Power=0;
    }
    paramChanged = 1; // Отмечаем, что требуется запись в eeprom 
    pChangeSec = Sec; // Отметка времени последнего изменения
    reDisplayData++;
    break;
  }
}


// Прерывание управления симистором.
ISR(TIMER1_COMPA_vect) 
{
  // Включаем симистор
  if (UstPower>0 && PowerEnabled) digitalWrite(PIN_TRIAC,HIGH);
}


ISR(ADC_vect)
{
  static unsigned int prev_tic = 0;
  static char pad = 0;
  unsigned int tic;

  VolVal = ADCL|(ADCH << 8);

  // Пропускаем каждые 4 отсчета
  if (++pad<5) return;
  pad = 0;

  tic = (uint16_t) TCNT1L | (uint16_t) (TCNT1H<<8); // Расчитывааем текущее значение таймера

  // Обходим сброс таймера по прерыванию нуля
  if (prev_tic < tic) prev_tic = tic;
  else tic = prev_tic + tic;

  
  
  if (VolVal < 2) {
    
    // Если дана команда рассчитать среднеквадратичное, или среднеквадратичное рассчитывается, но 0 встретился раньше, чем положено, то запускаем расчет заново.        
    if (StateVolts==0 || (StateVolts==1 && ticIndex<=20)) {
        ticIndex=0;
        StateVolts=1; 
        tic=0;  
        MaxVolts=0;
        prev_tic = 0;
      }
    }

    // Если ноль встретился и процесс расчета идет, тогда ставим флаг окончания процесса.
    if (StateVolts==1 && ticIndex > 80) {
      if (MaxVolts>100) {
        // Если максимальное напряжение менее 100 вольт - дропаем результаты и начинаем заного
        data_adc[ticIndex] = VolVal;
        tic_adc[ticIndex] = tic;
        ticIndex++;
        StateVolts=2;     
        MaxVoltsOut=MaxVolts;
        prev_tic = 0;
      } else {
        StateVolts = 0;
      }                 
  }

  // Если процесси идет, тогда просто накапливаем значения измерений
  if (StateVolts==1) {
    data_adc[ticIndex]=VolVal;
    tic_adc[ticIndex]=tic;
    
    if (ticIndex==1) {
      // при первом ненулевом результате фиксируем дельту
      deltaArray[deltaIndex++] = tic;
      if (deltaIndex>=16) deltaIndex=0;
    }
    
    ticIndex++;
    if (VolVal>MaxVolts) MaxVolts=VolVal;
  }

  // Если превышен размер массива, то считаем эту выборку несостоятельной (Вдруг глюк АЦП или помеха в сети), начинаем снова.
  if (ticIndex>=MAX_INDEX_INPUT)  StateVolts=0;
}

// 2 Прерывание вызывается 125 раз в секунду
ISR(TIMER2_COMPA_vect) 
{
  if (Counter1 % 20 ==0) {
    if (StateVolts==4)  {
      StateVolts=0; // Раз в 1/5 секунды запускаем измерение среднеквадратичного (в дальнейшем можно будет настроить, 
                    // чтобы оно делалось так часто, насколько позволяют возможности контроллера).
    }
  }

  // Следим за защитой от дребезга клавиш
  if (Counter1 % 20 ==0) {              
    if (CountKeys>0) CountKeys--;
  }
  
  Counter1++;
  if (Counter1>=125) {
    reDisplayData++; // обновляем дисплей
    Sec++;
    Counter1=0;
   }  
   
  // Сброс таймера
  TCNT2=0x00;
}


// Функция вызывается по прерыванию нуля от нуля сети 220 вольт
void zero_crosss_int()  // function to be fired at the zero crossing to dim the light
{
  unsigned int TimeOpenTriacFact=0;
  // Сбрасываем таймер.
  TCNT1H=0x00;
  TCNT1L=0x00;
  if (UstPower>=Power) {
    // Если мощность больше или равна номинальной, включаем триак всегда, при этом прерывание на закрытие никогда не выполнится.  
    TimeOpenTriac=5000;
  } else {
    digitalWrite(PIN_TRIAC,LOW);
  }

  // время открытие + ошибка прохождения нуля
  TimeOpenTriacFact = TimeOpenTriac + deltaZ;
    
  // В прерывании нуля настраиваем, чтобы прерывание на 1-м таймере выдалось через то время, которое мы ранее рассчитали.
  OCR1AH=(char)(TimeOpenTriacFact>>8);
  OCR1AL=(char)TimeOpenTriacFact;
}


void loop() 
{
  char *Command = NULL, *ptr, *ptr2;
  unsigned int Val;
  int i,j, s;
  unsigned long SqNapr=0,SqNaprPrev=0,FindPower;
  unsigned int TimeOpenTriac1=0;
  char s_rx;

  // Опрос нажатия кнопки валкодера (S)
  if (!CountKeys) {
    if (LOW == digitalRead(PIN_VOLC_S)) {
      StateMachine++;
      if (StateMachine>MAX_MODE) StateMachine = MIN_MODE;
      paramChanged = 1; // Отмечаем, что требуется запись в eeprom 
      pChangeSec = Sec; // Отметка времени последнего изменения
      reDisplayData++;
      CountKeys=2; // защита от дребезга
    }
  }
  
  // Проверка необходимости записа изменений в eeprom, если небыло дальнейших изменений
  // в течении 5 секунд. Это сделано, чтобы валкодером не протереть в ней дырку
  if (paramChanged>0 && pChangeSec>0 && Sec > pChangeSec+5) {
    writeEEPROM();
    paramChanged = 0;
    pChangeSec = 0;
  }

  // Обработка принудительного обновления информации на дисплее
  if (reDisplayData) dispData();
  
  if (LSec != Sec) {
    LSec = Sec;
    sprintf(tbuffer,"DATA %u %u %u %u %u", PowerEnabled, Power, UstPower, Sec, MaxVoltsOut*707/1000);
    Serial1.println(tbuffer);
  }

  
  if (Serial.available() > 0) {
    //если есть доступные данные считываем байт
    s_rx=Serial.read();
    if (s_rx == '\r') {


      RBuffer[PosRx]=0;
      PosRx=0;

#ifdef DEBUG      
      /* Отладка - возврат строки */
      Serial.print("dbg: ");
      Serial.println(RBuffer);
#endif /* DEBUG */

      // передаем данные в следующем формате:
      // сколькоприбавитьсекунд,Темпереатура1,Температура2, Температура3
      ptr = RBuffer;
      ptr2=strchr(ptr,',');
      if (ptr2) {
        *ptr2++ = 0;
        Command = ptr;
        Val = atoi(ptr2);
        if(!strcmp(Command,"MAXP")) {
          /* Установка номинальной мощности тэнов */
          Power=Val;
          sprintf(tbuffer,"MAXP: %u", Power);
          FlUsart++;
        } else if(!strcmp(Command,"ENABLE")) {
          /* Включение иил выключение напряжения на нагрузке */
          PowerEnabled = Val;
          sprintf(tbuffer,"ENABLE: %u", Val);
          FlUsart++;
        } else if(!strcmp(Command,"POWER")) {
          /* Установка мощности на нагрузке */
          UstPower = Val;
          if (UstPower > Power) UstPower = Power;
          sprintf(tbuffer,"POWER: %u", UstPower);
          FlUsart++;
        }
      }
    } else {
      /* не символ возврата коретки - помещаем в буфер */
      if (PosRx>=RX_BUFFER_SIZE) PosRx=0;
      RBuffer[PosRx++]=s_rx;
    }
  }
  // Окончание анализа асинхронного порта 

  if (FlUsart>0) {
      // Признак того, что надо выдать информацию в ком-порт (есл ее вдруг невозможно сразу выдать, например, из прерывания).
      Serial1.println(tbuffer);
      FlUsart=0;    
  }       
  
  // Начало расчета среднеквадратичного
  if (StateVolts==2){
    // Расчитываем  среднее смещение прерывания нуля и реального нуля
    uint16_t deltaSum=0;
    for(i=0;i<16;i++) deltaSum += deltaArray[i];
    deltaZ = deltaSum >> 4; // деление на 16
    StateVolts=3;
    
#ifdef DEBUG
    Serial1.println("BEGIN SQNAPR");
#endif /* DEBUG */


    // поскольку тут идет преобразование и умножение 32 разрядных чисел, делаем это по необходимости, а не каждый раз
    TekPower=(unsigned long) UstPower*220*220/ Power;
    SqNapr= SqNaprPrev= TimeOpenTriac1=0;
    FindPower=TekPower*ticIndex;

    if (UstPower < Power) {
      for(i=ticIndex-1; i>=0; i--) {
        SqNapr += (unsigned long) data_adc[i]* (unsigned long) data_adc[i];
        if (SqNapr>=FindPower)  { 
          // Рассчитали среднеквадратичное
          OpenTriacArray[OpenTriacIndex++] = tic_adc[i] + (SqNapr-FindPower)*(tic_adc[i+1]-tic_adc[i])/(SqNapr-SqNaprPrev);
          if (OpenTriacIndex>=16) OpenTriacIndex=0;
          
          for(j=0; j<16; j++) TimeOpenTriac1 += OpenTriacArray[j];
          TimeOpenTriac = TimeOpenTriac1 >>4; // деление на 16

          // Присвоили текущие значения
          TicSqNapr=tic_adc[ticIndex-1]; // Количство тиков таймера, на основании которого расчитано среденеквадратичное.
          break;
        }
        SqNaprPrev=SqNapr;
      }
    }      
static int jj=0;
#ifdef DEBUG
    Serial1.println("VOLTS");
  
    sprintf(tbuffer,"Zr=%4u %u",TimeOpenTriac,OpenTriacIndex);
    Serial1.println(tbuffer);

    sprintf(tbuffer,"Pm/P=%u %u", Power,(long) UstPower);
    Serial1.println(tbuffer);

    sprintf(tbuffer,"Zr=%4u U=%3u",TimeOpenTriac,(long) MaxVoltsOut*707/1000);
    Serial1.println(tbuffer);

    sprintf(tbuffer,"COUNT=%u",ticIndex);
    Serial1.println(tbuffer);
/*
    for(i=0;i<ticIndex;i++){
      // Данные для построения графика напряжения 
      sprintf(tbuffer,"$t[%u][", jj);
      Serial1.print(tbuffer);
      sprintf(tbuffer,"%u]=",tic_adc[i]);      
      Serial1.print(tbuffer);
      Serial1.print(data_adc[i]);
      Serial1.println(";");
    }
    jj++;
*/
    sprintf(tbuffer,"deltaZ=%u %u", deltaZ, TicSqNapr);
    Serial1.println(tbuffer);      
    Serial1.println("ENDVOLTS");
          
    
#endif /* DEBUG */
    StateVolts=4;
  } // окончание  расчета среднеквадратичного

}