Повёрнутый ? в Serial.print

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

День добрый! Подскажите, что означает повёрнутый знак вопроса: 

01:58:55.364 -> ⸮ 

Я понимаю какая-то ошибка в коде у меня, но может быть понимание этого знака ускорит нахождение ошибки...

RxMaxx
Offline
Зарегистрирован: 10.04.2020

Скорости сериал-монитора и в Serial.begin совпадают?

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Да, скорости совпадают... 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

А какой код у этого знака (если хексом напечатать) ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexBajdin59rus пишет:
что означает повёрнутый знак вопроса:
Он означает начало вопросительного предложения в испанском языке.  А в конце ставится обычный вопросительный знак. Например:

¿De verdad quieres saber eso? (Вы действительно хотите это знать?)

Вопрос в примере выбран не случайно - Вы задали странный вопрос (не имеющий отношения к Вашему коду), а сам код не привели. И какого ответа Вы ждёте? Мой ответ абсолютно точный :-)

b707
Онлайн
Зарегистрирован: 26.05.2017

ЕвгенийП пишет:

¿De verdad quieres saber eso? (Вы действительно хотите это знать?)

позанудствую - если быть точным, в этом предложении обращение не на "Вы", а на "ты"

Ты действительно хочешь это знать?

У испанцев. аналогично нам, и в отличии от анлосаксов, есть разделение на фамильярное "ты" и вежливое "Вы"

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

:-)))

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Какой код знака, если хексом напечатать, не знаю как узнать, ANSI кодировку такую не нашёл.

На счёт испанского знака, не то - знак повёрнут относительно вертикальной оси, а не горизонтальной:

14:18:01.756 -> ⸮

Бывает такое, что должно вывести, например, значение поля структуры:

Serial.println("Data_Control.data_lcd.mode = " + String(Data_Control.data_lcd.mode));

А выводит Data и бесконечное количество символов "⸮":

Data⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

Кто сталкивался с таким, о чём это говорит...?

Если приводить код, то трудно будет в нём разобраться, да и схему подключения нужно сделать. Причём есть очень интересный момент для меня - в операторе выбора SWITCH если я поменяю местами case 0: и case 1: всё работает прекрасно... Приведу код нерабочий:

switch (Data_Control.data_lcd.mode)
    {case 0: switch (digit_func)
                 {case 1: chang_enable(&Data_Control); break;    
                  case 2: chang_mode(&Data_Control);   break;
                  case 3: chang_step_size(MINUS, &Data_Control); break;
                  case 4: chang_step_size(PLUS, &Data_Control);  break;
                  case 5: timer_or_manual(&Data_Control);  break;       
                  case 6: chang_mode_level(&Data_Control); break;       
                  case 7: break;
                  case 8: break;
                  case 14: break;
                  case 15: Start_Timer_Motor(&Data_Control); break;     
                  case 16: chang_level(&Data_Control); break;           
                  default: break;
                 }       
             break;
     case 1: switch (digit_func)
                 {case 1: chang_enable(&Data_Control);   break;
                  case 2: chang_mode(&Data_Control);     break;
                  case 3: chang_step_size(MINUS, &Data_Control); break;     
                  case 4: chang_step_size(PLUS, &Data_Control);  break;     
/*                case 5: chang_rpm(MINUS, &Data_Control);   break;         
                  case 6: chang_rpm(PLUS, &Data_Control);   break;          
                  case 7: cng_total_imp(&Data_Control);   break;            
                  case 8: chang_dir(&Data_Control);   break;                
                  case 9: chang_imp(MINUS, &Data_Control);   break;         
                  case 10: chang_imp(PLUS, &Data_Control);   break;         
                  case 11: break;    
                  case 12: break;    
                  case 13: break;
*/                case 14: START_MOTOR(&Data_Control);   break;
                  case 15: PAUSE_MOTOR(&Data_Control);   break;
                  case 16: STOP_MOTOR(&Data_Control);    break;
                  default: break;
                 }
              break;
     default: break;
    }

и рабочий:

switch (Data_Control.data_lcd.mode)
    {case 1: switch (digit_func)
                 {case 1: chang_enable(&Data_Control);   break;
                  case 2: chang_mode(&Data_Control);     break;
                  case 3: chang_step_size(MINUS, &Data_Control); break;     
                  case 4: chang_step_size(PLUS, &Data_Control);  break;     
/*                case 5: chang_rpm(MINUS, &Data_Control);   break;         
                  case 6: chang_rpm(PLUS, &Data_Control);   break;          
                  case 7: cng_total_imp(&Data_Control);   break;            
                  case 8: chang_dir(&Data_Control);   break;                
                  case 9: chang_imp(MINUS, &Data_Control);   break;         
                  case 10: chang_imp(PLUS, &Data_Control);   break;         
                  case 11: break;    
                  case 12: break;    
                  case 13: break;
*/                case 14: START_MOTOR(&Data_Control);   break;
                  case 15: PAUSE_MOTOR(&Data_Control);   break;
                  case 16: STOP_MOTOR(&Data_Control);    break;
                  default: break;
                 }
              break;
     case 0: switch (digit_func)
                 {case 1: chang_enable(&Data_Control); break;    
                  case 2: chang_mode(&Data_Control);   break;
                  case 3: chang_step_size(MINUS, &Data_Control); break;
                  case 4: chang_step_size(PLUS, &Data_Control);  break;
                  case 5: timer_or_manual(&Data_Control);  break;       
                  case 6: chang_mode_level(&Data_Control); break;       
                  case 7: break;
                  case 8: break;
                  case 14: break;
                  case 15: Start_Timer_Motor(&Data_Control); break;     
                  case 16: chang_level(&Data_Control); break;           
                  default: break;
                 }       
             break;

     default: break;
    }

 

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexBajdin59rus пишет:

Бывает такое, что должно вывести, например, значение поля структуры:

Serial.println("Data_Control.data_lcd.mode = " + String(Data_Control.data_lcd.mode));

А выводит Data и бесконечное количество символов "⸮":

Data⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮

Кто сталкивался с таким, о чём это говорит...?

о том, что вы пытаетесь вывести на печать непечатные символы.

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Непечатные символы... Тогда при каких условиях это может произойти...? В Serial.print вставляю ведь правильные аргументы по синтаксису... Что у меня не так может быть в коде. Отправить архивом весь код тогда что-ли... Может кто взглянет

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexBajdin59rus пишет:

Непечатные символы... Тогда при каких условиях это может произойти...?

Это происходит, когда вы слишком полагаетесь на компилятор. Зачем вы преобразуете аргументы в String? Что там в аргументах - числа? Символы, строки? массив? - для каждого типа аргументов делайте вывод отдельно в соответвии с типом

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Хорошо, тогда что Вы скажите про нормальный вывод в остальных частях кода? Там я пишу также подобно как строку название переменной и её значение 

Serial.println("Data_Control.data_lcd.mode = " + String(Data_Control.data_lcd.mode));

выводит 

Data_Control.data_lcd.mode = 1

Тут дело (в символах ⸮⸮⸮⸮⸮⸮⸮⸮⸮) в чём-то другом, в какой-то моей ошибке в коде, где я пока не могу разобраться...

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexBajdin59rus пишет:

Хорошо, тогда что Вы скажите про нормальный вывод в остальных частях кода?

Тут дело в чём-то другом, в какой-то моей ошибке в коде, где я пока не могу разобраться...

А что у вас памятью? Ее достаточно? Скетч то вообще большой?

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Скетч небольшой, на Мега2560 6% всего занимает флеша и 10% используют глобальные переменные

sadman41
Offline
Зарегистрирован: 19.10.2016

Вы бы спросили - на каком языке товарищ записал строки в скетч.

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Попрошу поподробнее об этом

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexBajdin59rus, знаете что мне интересно? Вы ещё неделю будете тут плач Ярославны разводить или, наконец, снимете гриф секретности со своего скетча и покажете его нам?

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Я реально не могу понять свою ошибку, уже по всякому тут пробую. Выше писал про интересный момент, который на мой взгляд кажется какой-то чепухой, а для остальных скажут что не может такого быть. Я могу выложить код, но как в нем разобраться без составления схемы всей? И ещё, как тут архивом выложить весь скетч? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А кому нужен "весь скетч"?

У Вас что-то не так печатается, так ведь?

Удалите половину скетча и посмотрите, проблема сохранилась? Если нет - вернитесь и удалите другу половину. От того, что осталось удалите ещё половину. И так пока не получите МИНИМАЛЬНЫЙ работающий скетч в котором проблема сохраняется (желательно без необходимости иметь какое-то железо).

Скорее всего, когда скетч с проблемой станет маленьким, Вы и сами всё поймёте. Если же нет - выкладывайте сюда маленький скетч демонстрирующий проблему (остальное-то зачем). Только работающий, чтобы, например, я мог его запустить и увидеть проблему сам.

Оно так всегда и делается - проблема локализуется во всё меньшем и меньшем кода пока код не станет совсем крохотным и очевидным.

Пока же тема выглядит так: в скетче, которого никто не видел что-то не так печатается. И чего Вы от такой темы ожидаете?

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Ребята, всем спасибо! Вопрос снят, сам теперь не пойму как сделал... Закомментировал много чего, потом гляжу, у меня в одном из mode_1.h осталась по забывчивости декларация (или как правильно назвать функцию в этом файле), функцию которой я удалил из-за ненадобности в mode_1.ino. Удалив запись в mode_1.h и раскомментировав обратно часть кода всё заработало. Сам не понял как решил вопрос, потому что для интереса захотел вернуть обратно ситуацию, записав обратно в mode_1.h *левую* функцию, Мега отрабатывает как нужно... Если разберусь в старых версиях скетча отпишусь обязательно )

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexBajdin59rus пишет:

Закомментировал много чего, потом гляжу, ...

Это примерно то, о чём я писал Вам чуть выше.

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Не ребята, у меня скоро или бзик по фазе будет или у меня руки кривые... Вот привожу часть кода, где мне и другим ясно, что похер где вставлена функция SerialPrintVAR();

// ********************************************************
// кнопка MODE
void chang_mode(DATA_CONTROL *_Data_Control)
{ STOP_MOTOR(&Data_Control);
  A4988_OFF(&Data_Control);
  _Data_Control->data_lcd.mode++;
  if (_Data_Control->data_lcd.mode == MAX_MODE)
      _Data_Control->data_lcd.mode = 0;
  switch (_Data_Control->data_lcd.mode)
        {case 0: init_mode_0();
                 lcd_mode_0();
                 SerialPrintVAR();
                 break;
         case 1: init_mode_1();
                 lcd_mode_1();
                 SerialPrintVAR();
                 break;
         default: break;
        }
  SerialPrintVAR();
  Serial.println("Data_Control.data_lcd.mode = " + String(Data_Control.data_lcd.mode));
  Serial.println(" ");
  lcd.noBlink();
}

Сама SerialPrintVAR(); вот:

void SerialPrintVAR()
{ VAR_TCNTx = pgm_read_word(&ARR_TCNTx[Data_Control.data_dvig.size_step][Data_Control.data_dvig.rpm]);
  VAR_OCRxA = pgm_read_word(&ARR_OCRxA[Data_Control.data_dvig.size_step][Data_Control.data_dvig.rpm][Data_Control.data_dvig.imp_cnt]); 
  VAR_TCCRxB = pgm_read_byte(&ARR_CS[Data_Control.data_dvig.size_step][Data_Control.data_dvig.rpm]);   // выбор предделителя
  
  Serial.println("Data_Control.data_dvig.size_step = " + String(Data_Control.data_dvig.size_step));
  Serial.println("Data_Control.data_dvig.rpm = " + String(Data_Control.data_dvig.rpm));
  Serial.println("VAR_TCNTx = " + String(VAR_TCNTx));
  Serial.println(" ");
  Serial.println("Data_Control.data_dvig.size_step = " + String(Data_Control.data_dvig.size_step));
  Serial.println("Data_Control.data_dvig.rpm = " + String(Data_Control.data_dvig.rpm));
  Serial.println("Data_Control.data_dvig.imp_cnt = " + String(Data_Control.data_dvig.imp_cnt));
  Serial.println("VAR_OCRxA = " + String(VAR_OCRxA));
  Serial.println(" ");
  Serial.println("Data_Control.data_dvig.size_step = " + String(Data_Control.data_dvig.size_step));
  Serial.println("Data_Control.data_dvig.rpm = " + String(Data_Control.data_dvig.rpm));
  Serial.println("VAR_TCCRxB = " + String(VAR_TCCRxB));
  Serial.println("*******************************************************");
}

БЛИН, КАКАЯ НАХЕР РАЗНИЦА, СКОЛЬКО БУДЕТ ЭТИХ SerialPrintVAR(); - ОНА ВЕЗДЕ ДОЛЖНА ОТРАБАТЫВАТЬ, ТАК БЛЯ В ПЕРВОМ ПРИВЕДЕНИИ КОДА (В ФУНКЦИИ void chang_mode(DATA_CONTROL *_Data_Control)) раскомментированием/закомментированием SerialPrintVAR(); то работает АРДУИНО нормально, то не работает, причём возвращаю обратно двойной слеш как было, работает противоположно (если не работало, то работает и наоборот).

Также вопрос, я думаю что также похер что в loop()

void loop() {
 while(1)
  {switch (Data_Control.data_lcd.mode)
       {case mode_1: VAR_TCNT3 = pgm_read_word(&ARR_TCNT3[Data_Control.data_dvig.size_step][Data_Control.data_dvig.rpm]);
                     VAR_OCR3A = pgm_read_word(&ARR_OCR1A[Data_Control.data_dvig.size_step][Data_Control.data_dvig.rpm][Data_Control.data_dvig.imp_cnt]);    
                     VAR_TCCR3B = pgm_read_byte(&ARR_CS[Data_Control.data_dvig.size_step][Data_Control.data_dvig.rpm]);   // выбор предделителя
                     break;
        case mode_4: //if (Data_Control.data_mode_4.chang_data_timer_flag)
                     // get_data_timer_mode_4(&Data_Control);
                     break;
        default: break;
       }

похер что когда наступил mode == mode_1 в переменные VAR... должны читаться из флеша и не мешать нормальной работе программе (выражается что выводится перевернутый "?" и ардуино как-бы тормозит, также и про SerialPrintVAR(); описанный выше). У меня вопрос: ARDUINO IDE у меня глючная (1.8.12 версия) или может задрочил Мегу2560 свою? Сколько раз можно прошивать Мегу, вроде 10000 раз гарантированно?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AlexBajdin59rus пишет:

Не ребята, у меня скоро или бзик по фазе будет 

Похоже, что уже.

Я же Вам ясно писал

ЕвгенийП пишет:
выкладывайте сюда маленький скетч демонстрирующий проблему (остальное-то зачем). Только работающий, чтобы, например, я мог его запустить и увидеть проблему сам.

А Вы что выложили? Запустить я это не могу, а сидеть, пялиться на него и догадываться, что у Вас там ещё написано - увольте.

Перечитайте тот мой пост ещё раз, если действительно нужна помощь. А если не нужна, а только в жилетку поплакаться, тогда продолжайте.

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Еще раз всем привет! Продолжу о своей проблеме. Я по совету Евгения так и сделал, уменьшил код до минимума. Было у меня 4 режима управления двигателем, удалил файлы с функциями начиная со второго режима, первый режим работал прекрасно, потихоньку добавлял второй режим. Но ошибка в работе сохраняется. Вы будите смеяться наверное, но для меня пока реально загадка: как при добавлении операторов переключателей CASE в SWITCH, происходит ошибка. Выглядит это так:

switch (Data_Control.data_lcd.mode)
   {case mode_0: switch (digit_func)
                    {case 1: chang_enable(&Data_Control); break;    
                     case 2: chang_mode(&Data_Control);   break;
                     case 3: chang_step_size(MINUS, &Data_Control); break;  
                     case 4: chang_step_size(PLUS, &Data_Control);  break;  
                     case 5: timer_or_manual(&Data_Control);  break;        
                     case 6: chang_mode_level(&Data_Control); break;        
                     case 15: Start_Timer_Motor(&Data_Control); break;     
                     case 16: chang_level(&Data_Control); break;           
                     default: break;
                    }       
                  break;
    case mode_1: Serial.println(" ПОПАЛИ В MODE_1");
                 switch (digit_func)
                    {case 1: Serial.println(" ПОПАЛИ В CASE 1");  
                             chang_enable(&Data_Control);   break;
                     case 2: Serial.println(" ПОПАЛИ В CASE 2");  
                             chang_mode(&Data_Control);     break;
                     case 3: chang_step_size(MINUS, &Data_Control); break; 
                     case 4: chang_step_size(PLUS, &Data_Control);  break;
                     case 5: chang_rpm(MINUS, &Data_Control);   break;    
                     case 6: chang_rpm(PLUS, &Data_Control);   break;     
                     case 7: cng_total_imp(&Data_Control);   break;       
                     case 8: chang_dir(&Data_Control);   break;           
                     case 9: chang_imp(MINUS, &Data_Control);   break;    
                     case 10: chang_imp(PLUS, &Data_Control);   break;    
                     case 14: START_MOTOR(&Data_Control);   break;
                     case 15: PAUSE_MOTOR(&Data_Control);   break;
                     case 16: STOP_MOTOR(&Data_Control);    break;
                     default: break;
                    }
                  break;
            default: break;
   }

Теперь смотрим с самого верха. При нажатии клавы 4 * 4 сначала определяется режим MODE, у меня их 2. 

switch (Data_Control.data_lcd.mode)

Кнопки (функции) первого режима работают хорошо. Кнопкой 2 включаем второй режим. Далее, когда включен режим №2, при нажатии, допустим кнопки №1 (вкл/выкл драйвера двигателя) или кнопки №2 (переключение на режим №1) в мониторе порта должно быть следующее:

 ПОПАЛИ В MODE_1 
 ПОПАЛИ В CASE 2

но в мониторе порта есть только это:

 ПОПАЛИ В MODE_1
⸮

Теперь вопрос знатокам: как может быть такое, если закомментирую строки с переключателями case 3: -> case 16:, всё работает и выводится в монитор как положено...?

Также работает без ошибок и выводится нормально в монитор, если я вырежу полностью case mode_0:

case mode_0: switch (digit_func)
                            {case 1: chang_enable(&Data_Control); break;    
                             case 2: chang_mode(&Data_Control);   break;
                             case 3: chang_step_size(MINUS, &Data_Control); break;  
                             case 4: chang_step_size(PLUS, &Data_Control);  break;  
                             case 5: timer_or_manual(&Data_Control);  break;        
                             case 6: chang_mode_level(&Data_Control); break;      
                             case 15: Start_Timer_Motor(&Data_Control); break;    
                             case 16: chang_level(&Data_Control); break;           
                             default: break;
                            }       
                         break;

и помещу ниже case 1:, то есть поменяю местами обработчики case 0 и case 1.  Для наглядности покажу функцию переключения режимов кнопкой №2:

// ********************************************************
// кнопка MODE
void chang_mode(DATA_CONTROL *_Data_Control)
{ //STOP_MOTOR(&Data_Control);
  //A4988_OFF(&Data_Control);
  _Data_Control->data_lcd.mode++;
  if (_Data_Control->data_lcd.mode == MAX_MODE)
      _Data_Control->data_lcd.mode = 0;
  switch (_Data_Control->data_lcd.mode)
        {case 0: init_mode_0();
                 lcd_mode_0();
                 break;
         case 1: init_mode_1();
                 lcd_mode_1();
                 break;
         default: Serial.println("Был: default: break;");
                    break;
        }
  Serial.println("Data_Control.data_lcd.mode = " + String(Data_Control.data_lcd.mode));
  Serial.println(" ");
  lcd.noBlink();
}

MAX_MODE, то есть если стало 2, то сделаем mode == 0. Я вставлял Serial.print для проверки изменения Data_Control.data_lcd.mode, там изменяется как надо. Но вот когда этот режим равен №1, эти Serial.print не работают, о чем я писал выше.

Всем заинтересовавшимся в такой интересной штуке могу выложить код через электронку (abajdin_59rus@mail.ru). Также мой тел 89125954026. Сделайте дозвон - позвоню сам. Здесь я могу выложить код, но куча файлов и много текста не уместятся нормально на форуме. Евгений, я бы очень хотел получить Вашу помощь, мы можем списаться через электронку или по телефону? Нужно для этого ARDUINO MEGA, LCD 20*4, клава 4*4 или даже одна кнопка, плата для связи LCD и ARDUINO по I2C. 

Огромное спасибо откликнувшимся!

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexBajdin59rus, вы, похоже, не понимаете, что вам пишут. Евгений что просил? - Чтобы вы упростили и уменьшили код до такого размера, чтобы он не требовал кучи файлов и мог быть выложен в форум. А вы опять вывалили какие-то отдельные функции к кучей путанных обьяснений.

Не буду говорить за Евгения, но от меня вам совет - упростите код только до вложенных switch и case, удалите нафиг LCD экран и все свои зубодробительные функции типа chang_mode() chang_step() и так далее. Замените их просто выводом в монитор, примерно так:

case mode_0: switch (digit_func)
                            {case 1: Serial.println(" Case 1");break;    
                             case 2: Serial.println(" Case 2");break;    
                             case 3: Serial.println(" Case 3");break;     
                             case 4: Serial.println(" Case 4");break;    
                            .....   
                             default: break;
                            }       
                         break;

В итоге вам нужно получить скетч длиной страничку или две, не больше - и без использования каких-либо внешнизх файлов и библиотек.

Вот такой код и выложите в форум.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

B707 всё правильно написал, но я ещё дополню. Ключевым в моём совете было: "чтобы, например, я мог его запустить и увидеть проблему сам". Т.е. от Вас ждут цельного кода, а не кусков.

Вот Вы пишете

AlexBajdin59rus пишет:
уменьшил код ... Но ошибка в работе сохраняется

Значит, ещё уменьшайте. Сократите Вы его до полусотни строк, тогда либо сам разберётесь, либо Вам помогу. Но продираться сквозь Ваши куски (по пути догадываясь, а что там ещё есть)  никто не будет

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Ребята, написал здесь было много чего хотел сказать, но всё случайно стёрлось, переписывать очень много, поэтому напишу теперь кратко. Уменьшил код по максимальному, далее уменьшать - работает без ошибок. Но чтоб вы не думали что я мозги компассирую, работает без ошибок тогда, когда я удаляю код, который по логике алгоритма не работает. То есть, например, не нажал кнопку и по логике мы не попали в функцию обработки этой кнопки и при удаление этого кода всё отлично. Для тестирования достаточно замкнуть выводы А9 и А12  между собой. На PORTK у меня посажена клава 4*4. Это имитация нажатия кнопки переключения режимов. Файл MAIN:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
#include "1_MAIN_VAR.h"
#include "CONST.h"
#include "Init_my_MCU.h"
#include "LCD.h"
#include "mode_0.h"
#include "mode_1.h"
#include "work.h"

LiquidCrystal_PCF8574 lcd(0x27);

DATA_CONTROL Data_Control;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  Init_MCU();
}

void loop() {
 while(1)
  {if (change_butt_16 == 1)
      {TCCR2B = 0x00;    
       TCNT2 = 0x00;
       TIMSK2 = 0x00;
       switch (Data_Control.data_lcd.mode)
           {case mode_0: switch (digit_func)
                            {case 1: chang_enable(&Data_Control); break;    
                             case 2: chang_mode(&Data_Control);   break;
                             case 3: chang_step_size(MINUS, &Data_Control); break;  // Step_Size_--
                             case 4: chang_step_size(PLUS, &Data_Control);  break;  // Step_Size_++
                             case 5: timer_or_manual(&Data_Control);  break;        // настройка прокрутки от таймера или вручную
                             case 6: chang_mode_level(&Data_Control); break;        // уровни при ручном управлении 010 или 101
                             case 15: Start_Timer_Motor(&Data_Control); break;     // МОТОР КРУТИТСЯ ОТ ИМПУЛЬСОВ ТАЙМЕРА 
                             default: break;
                            }       
                         break;
            case mode_1: Serial.println(" ПОПАЛИ В MODE_1"); 
                         switch (digit_func)
                            {case 1: Serial.println(" ПОПАЛИ В CASE 1");  
                                     chang_enable(&Data_Control);   break;
                             case 2: Serial.println(" ПОПАЛИ В CASE 2");  
                                     chang_mode(&Data_Control);     break;
                             case 3: chang_step_size(MINUS, &Data_Control); break;     // Step_Size_--
                             case 4: chang_step_size(PLUS, &Data_Control);  break;     // Step_Size_++
                             case 5: chang_rpm(MINUS, &Data_Control);   break;         // RPM_--
                             case 6: chang_rpm(PLUS, &Data_Control);   break;          // RPM_++  
                             case 7: cng_total_imp(&Data_Control);   break;            // IMP 1% or 5%
                             default: break;
                            }
                         break;
            default: break;
           }
        change_butt_16 = 0;
        finish = 1;      
        TCCR2B = 0x06;    
        TIMSK2 = 0x01;
       }
// ОБНОВЛЕНИЕ ЭКРАНА
  if (Data_Control.upd_lcd)
     {Serial.println("Были в update_lcd");
      update_lcd(&Data_Control);
      Data_Control.upd_lcd = 0;
     }
  }
}

Файл с объявлениями пременных:

#ifndef MAIN_VAR_H_
#define MAIN_VAR_H_

#define MAX_MODE 2    // ЧИСЛО РЕЖИМОВ + 1

#define MINUS 0x00
#define PLUS 0x01

#define MIN_SPEED 1
#define MAX_SPEED 30

#define DDR_BUTT_16 DDRK          // PORTK
#define PORT_BUTT_16 PORTK
#define PIN_BUTT_16 PINK

#define end_dreb_16 5
#define end_dreb_after 30

#define PORT_LED PORTB      

struct DATA_DVIG {
  uint8_t size_step;
  uint8_t upd_size_step;
  uint16_t rpm;
  uint8_t upd_rpm;
  uint8_t imp_cnt;
  uint8_t upd_imp_cnt;
};

struct DATA_LCD {
  uint8_t ENABLE_X, ENABLE_Y;
  uint8_t MODE_X, MODE_Y;
  uint8_t enable;
  uint8_t upd_enable;
  uint16_t mode;
};
enum {mode_0, mode_1, mode_2, mode_3, mode_4} modes;

struct DATA_MODE_0 {
  uint8_t upd_TMR_OR_MANUAL;
  uint8_t upd_mode_level;
  uint8_t upd_RUN_flag;
  uint8_t upd_PORT_level;
};

struct DATA_MODE_1 {
  uint8_t upd_total_imp;
  uint8_t upd_START_STOP;
};

struct DATA_CONTROL {
  DATA_DVIG  data_dvig;
  DATA_LCD data_lcd;
  DATA_MODE_0 data_mode_0;
  DATA_MODE_1 data_mode_1;
  uint8_t upd_lcd;
};

volatile uint16_t VAR_TCNTx, VAR_OCRxA;
volatile uint8_t VAR_TCCRxB;

volatile uint16_t var_cnt, PRINT;

volatile uint8_t digit_func, antidreb_16, finish, antidreb_after;
volatile uint8_t butt_16_flag, change_butt_16;

uint8_t digit_butt_16[4][4] = 
{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};

uint8_t i, j;

#endif

Файл с константами:

#ifndef CONST_H_
#define CONST_H_

const uint8_t CS PROGMEM = 3;
const uint16_t TCNTx PROGMEM = 53036;
const uint16_t OCRxA PROGMEM = 53161;

#endif /* CONST_H_ */

Инициализация

#ifndef INIT_MY_MCU_H_
#define INIT_MY_MCU_H_

void Init_MCU();
void init_data_Dvig();
void init_var();
void init_mode_0();
void init_mode_1();

#endif /* INIT_MY_MCU_H_ */
void Init_MCU()
{ init_data_Dvig();
  init_var();
  Data_Control.data_lcd.enable = 1;
  Data_Control.data_lcd.mode = 0;
  Data_Control.upd_lcd = 0;
  init_mode_0();
  DDRB = 0xFF;  PORTB = 0x01;     // PORT_LED
  lcd.begin(20,4);
  lcd.clear();
  lcd.home();
  lcd.display();
  lcd_mode_0();
  TCCR2A = 0x00;
  TCCR3A = 0x00;
  TCCR2B = 0x06;    // clk/256
  TIMSK2 = 0x01;  
  sei(); 
}

void init_var()
{ digit_func = 0;
  butt_16_flag = 0;
  antidreb_16 = 0;
  antidreb_after = 0;
  change_butt_16 = 0;
  finish = 0;
}

void init_data_Dvig()     //  STRUCT dataDvig
{ Data_Control.data_dvig.size_step = 0;
  Data_Control.data_dvig.upd_size_step = 0;
}

void init_mode_0()      //  STRUCT DATA_MODE_0
{ init_data_Dvig();
  Data_Control.data_mode_0.upd_TMR_OR_MANUAL = 0;
  Data_Control.data_mode_0.upd_mode_level = 0;
  Data_Control.data_mode_0.upd_RUN_flag = 0;
  Data_Control.data_mode_0.upd_PORT_level = 0;  
}

void init_mode_1()       //  STRUCT DATA_MODE_1
{ init_data_Dvig();
  Data_Control.data_mode_1.upd_total_imp = 0; 
}

Функции LCD

#ifndef LCD_H_
#define LCD_H_

void lcd_mode_0();
void lcd_mode_1();
void update_lcd(DATA_CONTROL *_Data_Control);

#endif /* LCD_H_ */
//=====================================
// ДИСПЛЕЙ ПРИ MODE = 0
void lcd_mode_0()
{ lcd.setCursor(0,0);
  lcd.print("OFF M0  MANUAL  FULL");
  lcd.setCursor(0,1);
  lcd.print("010  LVL-0     STOP ");  
  lcd.setCursor(0,2); 
  lcd.print("                    ");  
  lcd.setCursor(0,3);
  lcd.print("                    ");  
}

//=====================================
 // ДИСПЛЕЙ ПРИ MODE = 1
void lcd_mode_1()
{ lcd.setCursor(0,0);
  lcd.print("OFF M1 FULL >> 0,5/s");
  lcd.setCursor(0,1);
  lcd.print("IMP 5 10%      STOP ");
  lcd.setCursor(0,2);
  lcd.print("                    ");
  lcd.setCursor(0,3);
  lcd.print("                    "); 
}

// ************************************************************************************
// ************************************************************************************
void update_lcd(DATA_CONTROL *_Data_Control)
// ============================ СНАЧАЛА ОСНОВНЫЕ ПАРАМЕТРЫ ============================ 
{// ************* ВКЛ - ВЫКЛ А4988 *************
  if (_Data_Control->data_lcd.upd_enable == 1)
     _Data_Control->data_lcd.upd_enable = 0;

// ************* ОБНОВИМ ДАННЫЕ МИКРОШАГА *************
  if (_Data_Control->data_dvig.upd_size_step == 1)
     _Data_Control->data_dvig.upd_size_step = 0;

// ************* ОБНОВИМ СКОРОСТЬ *************
  if (_Data_Control->data_dvig.upd_rpm == 1)
    _Data_Control->data_dvig.upd_rpm = 0;

// ************* ОБНОВИМ IMP от 1% до 50% *************
  if (_Data_Control->data_dvig.upd_imp_cnt == 1)
      _Data_Control->data_dvig.upd_imp_cnt = 0;

// ОБНОВЛЕНИЕ ТАЙМЕРА ИЛИ ВРУЧНУЮ
  if (_Data_Control->data_mode_0.upd_TMR_OR_MANUAL == 1)
      _Data_Control->data_mode_0.upd_TMR_OR_MANUAL = 0;
  
// ОБНОВЛЕНИЕ ПЕРИОДА ИЛИ РЕЖИМА НАЧАЛЬНОГО УРОВНЯ
  if (_Data_Control->data_mode_0.upd_mode_level == 1)
      _Data_Control->data_mode_0.upd_mode_level = 0;
   
// ОБНОВЛЕНИЕ СТАРТ СТОП РЕЖИМА
    if (_Data_Control->data_mode_0.upd_RUN_flag == 1)
       _Data_Control->data_mode_0.upd_RUN_flag = 0;
    
// ОБНОВЛЕНИЕ УРОВНЯ НА ВЫВОДЕ
  if (_Data_Control->data_mode_0.upd_PORT_level == 1)
      _Data_Control->data_mode_0.upd_PORT_level = 0;
  

}

Обработки нажатия кнопок

//*********************************************************************
// ********* Опрос клавы 4*4 ********* 
void Opros_Butt_16(uint8_t *i, uint8_t *j)
{ DDR_BUTT_16 = 0x0F;      // 0-3 выходы, 4-7 входы
  PORT_BUTT_16 = 0xF0;     // на выходах "0", на входах подтяжка к "1"
  delayMicroseconds(10);
  *i=4;
  if ((PIN_BUTT_16 & 0x10)==0x00) *i=0;    //       
  if ((PIN_BUTT_16 & 0x20)==0x00) *i=1;    //
  if ((PIN_BUTT_16 & 0x40)==0x00) *i=2;    //
  if ((PIN_BUTT_16 & 0x80)==0x00) *i=3;    //
  DDR_BUTT_16 = 0xF0;        // 0-3 вход, 4-7 выходы
  PORT_BUTT_16 = 0x0F;    // на выходах "0", на входах подтяжка к "1"
  delayMicroseconds(10);
  *j=4;
  if ((PIN_BUTT_16 & 0x01)==0x00) *j=0;    //
  if ((PIN_BUTT_16 & 0x02)==0x00) *j=1;    //
  if ((PIN_BUTT_16 & 0x04)==0x00) *j=2;    //
  if ((PIN_BUTT_16 & 0x08)==0x00) *j=3;    //    
}

// =========== Таймер_2 для обработки клавиатуры ============
ISR(TIMER2_OVF_vect)
{uint8_t i, j; 
 var_cnt++;
 if (var_cnt == 150)
     PORT_LED ^= (1 << 7);
 if (var_cnt == 244)
    {PORT_LED ^= (1 << 7);
     var_cnt = 0;
    }

// Проход антидребезга после отжатия кнопки
 if (finish == 1)
    {antidreb_after++;
     if (antidreb_after == end_dreb_after)
        {antidreb_after = 0;
         finish = 0;
         return;
        }
     return;
    }   

// Фиксируем факт нажатия кнопки
 if (butt_16_flag == 0) 
  {Opros_Butt_16(&i, &j);
   if ((i != 4)&&(j != 4))
      {butt_16_flag = 1;
       return;
      } 
  }

// Проход антидребезга
 if ((butt_16_flag == 1) && (antidreb_16 != end_dreb_16))
    {antidreb_16++;
     if (antidreb_16 == end_dreb_16)   // прошли антидребезг?
         {Opros_Butt_16(&i, &j);
          if ((i != 4)&&(j != 4)) 
             {change_butt_16 = 1;
              digit_func = digit_butt_16[i][j];
              return;
             }
         }
     return;    
    }

// Кнопка была нажата, функция кнопки отработалась, кнопка отжата - значит finish делаем = 1
  if ((butt_16_flag == 1) && (antidreb_16 == end_dreb_16) && (change_butt_16 == 0))
  {Opros_Butt_16(&i, &j);
   if ((i == 4)&&(j == 4))
      {butt_16_flag = 0;
       antidreb_16 = 0;
       finish = 1;
      }
  }
}

//===============================================================
//====================   TIMER3_OVF_vect   ======================
ISR(TIMER3_OVF_vect)
{
  switch (Data_Control.data_lcd.mode)
       {case 0: TCNT3 = 40000;
                break;
        case 1: TCNT3 = VAR_TCNTx;
                OCR3A = VAR_OCRxA;
                TCCR3B = VAR_TCCRxB;
                break;
        default: break;
       }
}

//=================================================================
//====================   TIMER3_COMPA_vect   ======================
ISR(TIMER3_COMPA_vect)
{
}

Режим_0

#ifndef MODE_0_H_
#define MODE_0_H_

void timer_or_manual(DATA_CONTROL *_Data_Control);     // изменения от таймера или вручную
void chang_mode_level(DATA_CONTROL *_Data_Control);    // уровни 0110 или 1001
void Start_Timer_Motor(DATA_CONTROL *_Data_Control);   // 

#endif /* MODE_0_H_ */
//==============================================================================
// импульсы будут от ТАЙМЕРА или ВРУЧНУЮ от кнопки
void timer_or_manual(DATA_CONTROL *_Data_Control)
{ _Data_Control->data_mode_0.upd_TMR_OR_MANUAL = 1;
  _Data_Control->upd_lcd = 1;
}

//==============================================================================
// ИЗМЕНИМ ФРОНТЫ (НАРАСТ., СПАД.) ПО НАЖАТИЮ КНОПКИ (01 или 10)
void chang_mode_level(DATA_CONTROL *_Data_Control)
{ _Data_Control->data_mode_0.upd_mode_level = 1;
  _Data_Control->upd_lcd = 1;
}

//==============================================================================
// ВКЛЮЧАЕМ МОТОР ЧЕРЕЗ ТАЙМЕР
void Start_Timer_Motor(DATA_CONTROL *_Data_Control)
{ _Data_Control->data_mode_0.upd_RUN_flag = 1;
  _Data_Control->upd_lcd = 1;
}

Режим_1

#ifndef MODE_1_H_
#define MODE_1_H_

void chang_rpm(uint8_t direct, DATA_CONTROL *_Data_Control);      // изменим скорость оборотов
void cng_total_imp(DATA_CONTROL *_Data_Control);                  // IMP 1% or 5%

#endif /* MODE_1_H_ */

//=====================================================================
// ИЗМЕНИМ СКОРОСТЬ ОБОРОТОВ
void chang_rpm(uint8_t direct, DATA_CONTROL *_Data_Control)
{ _Data_Control->data_dvig.upd_rpm = 1;
  _Data_Control->upd_lcd = 1;
}

//=====================================================================
// ИЗМЕНИМ ШАГ РЕГУЛИРОВКИ ИМПУЛЬСА (1% ИЛИ 5%)
void cng_total_imp(DATA_CONTROL *_Data_Control)
{ _Data_Control->data_mode_1.upd_total_imp = 1;
  _Data_Control->upd_lcd = 1;
}

Рабочие функции

#ifndef WORK_H_
#define WORK_H_

void chang_enable(DATA_CONTROL *_Data_Control);   // вкл/выкл A4899
void chang_mode(DATA_CONTROL *_Data_Control);     // изменение режима
void chang_step_size(uint8_t i, DATA_CONTROL *_Data_Control);     // изменим микрошаги

#endif /* WORK_H_ */
// ********************************************************
// кнопка ENABLE
void chang_enable(DATA_CONTROL *_Data_Control)
{ if (_Data_Control->data_lcd.enable == 0)  // драйвер работает? отключим его (ИНВЕРСИЯ !!!)
      {_Data_Control->data_lcd.enable = 1;
      } 
  else 
      {_Data_Control->data_lcd.enable = 0;
      }
  _Data_Control->data_lcd.upd_enable = 1;
  _Data_Control->upd_lcd = 1;
}

// ********************************************************
// кнопка MODE
void chang_mode(DATA_CONTROL *_Data_Control)
{ _Data_Control->data_lcd.mode = _Data_Control->data_lcd.mode + 1;
  if (_Data_Control->data_lcd.mode == MAX_MODE)
      {_Data_Control->data_lcd.mode = 0;
      }
  switch (_Data_Control->data_lcd.mode)
        {case 0: init_mode_0(); SerialPrintVAR(); SerialPrintVAR(); SerialPrintVAR();
                 lcd_mode_0();  //SerialPrintVAR(); SerialPrintVAR(); SerialPrintVAR();
                 break;
         case 1: init_mode_1(); SerialPrintVAR(); SerialPrintVAR(); SerialPrintVAR();
                 lcd_mode_1();  //SerialPrintVAR(); SerialPrintVAR(); SerialPrintVAR();
                 break;
         default: break;
        }
  SerialPrintVAR();
  Serial.println("Data_Control.data_lcd.mode = " + String(Data_Control.data_lcd.mode));
  Serial.println(" ");
  lcd.noBlink();
}

void SerialPrintVAR()
// В эти переменные у меня читались константы из флеша
{ Serial.println("VAR_TCNTx = " + String(VAR_TCNTx));
  Serial.println("VAR_OCRxA = " + String(VAR_OCRxA));
  Serial.println("VAR_TCCRxB = " + String(VAR_TCCRxB));
  Serial.println("*******************************************************");
}

//=====================================================================
// УСТАНОВКА РАЗМЕРА МИКРОШАГА
void chang_step_size(uint8_t i, DATA_CONTROL *_Data_Control)
{ uint8_t chang_flag = 0;
  switch (i)
      {case MINUS: if (_Data_Control->data_dvig.size_step != 0)   // не равен full
                      {_Data_Control->data_dvig.size_step--;
                       chang_flag = 1;
                      }
                   break;
       case PLUS: if (_Data_Control->data_dvig.size_step != 4)    // не равен 1/16
                     {_Data_Control->data_dvig.size_step++;
                      chang_flag = 1;
                     }
                  break;
       default: break;
      }
      
  if (chang_flag)
     {chang_flag = 0;
      _Data_Control->data_dvig.upd_size_step = 1;   // ОБНОВИМ РАЗМЕР МИКРОШАГА
      _Data_Control->upd_lcd = 1;
     }
}

 

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

Скажите, а зачем вам вывод в serial если есть дисплей? Я так думаю не успевает прерывания uart отрабатывать, поэтому и мусор в мониторе порта. Выделите на lcd пару символов/мест куда выводите свои режимы работы, будет гораздо нагляднее. Итоговое устройство будет же работать без монитора порта?

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Serialom я начал пользоваться когда у меня выявилась ошибка в работе, выяснял значения переменных. Было это как задержка обновления экрана либо вообще не обновлялся экран

 

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

сделаете в проекте что нибудь типа

#define DEBUG_MODE

и выводите в LCD отладочную информацию, потом в готовом проекте комментируйте строку и все будет в рабочем режиме.

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

andycat пишет:

сделаете в проекте что нибудь типа

#define DEBUG_MODE

и выводите в LCD отладочную информацию, потом в готовом проекте комментируйте строку и все будет в рабочем режиме.

Примерно понял Вашу мысль... но я думаю, что если в относительно простом моём коде не работает, то на ещё одном дополнительном режиме всё останется по прежнему.

b707
Онлайн
Зарегистрирован: 26.05.2017

AlexBajdin59rus пишет:

Примерно понял Вашу мысль... но я думаю, что если в относительно простом моём коде не работает, то на ещё одном дополнительном режиме всё останется по прежнему.

скажите, а зачем вы вообще сюда пишете?

Упрощать код вы не стали. любые советы отвергаете, сами ошибку тоже не ищете. С вашим настроем остается только завернутся в простыню и ползти на кладбище, шансов решить проблему у вас нет.

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Вот на что прошу обратить внимание. Я уже выложил свой код, вчера подробно описывал всё, но стерлось случайным образом, поэтому написал второпях. Теперь хочу поподробнее. Для меня кажется странной работа Ардуино и я уже думаю, не глючная ли она у меня. Мне её продали как б/у, может её 5 лет использовали и она теперь некорректно прошивается... Дело в чём, если смотреть на код:

void loop() {
 while(1)
  {if (change_butt_16 == 1)
      {TCCR2B = 0x00;    
       TCNT2 = 0x00;
       TIMSK2 = 0x00;
       switch (Data_Control.data_lcd.mode)
           {case mode_0: switch (digit_func)
                            {case 1: chang_enable(&Data_Control); break;    
                             case 2: chang_mode(&Data_Control);   break;
                             case 3: chang_step_size(MINUS, &Data_Control); break;  
                             case 4: chang_step_size(PLUS, &Data_Control);  break;  
                             case 5: timer_or_manual(&Data_Control);  break;        
                             case 6: chang_mode_level(&Data_Control); break;        
                             case 15: Start_Timer_Motor(&Data_Control); break;     
                             default: break;
                            }       
                         break;
            case mode_1: Serial.println(" ПОПАЛИ В MODE_1"); 
                         switch (digit_func)
                            {case 1: Serial.println(" ПОПАЛИ В CASE 1");  
                                     chang_enable(&Data_Control);   break;
                             case 2: Serial.println(" ПОПАЛИ В CASE 2");  
                                     chang_mode(&Data_Control);     break;
                             case 3: chang_step_size(MINUS, &Data_Control); break; 
                             case 4: chang_step_size(PLUS, &Data_Control);  break; 
                             case 5: chang_rpm(MINUS, &Data_Control);   break;     
                             case 6: chang_rpm(PLUS, &Data_Control);   break;      
                             case 7: cng_total_imp(&Data_Control);   break;        
                             default: break;
                            }
                         break;
            default: break;
           }
        change_butt_16 = 0;
        finish = 1;      
        TCCR2B = 0x06;    
        TIMSK2 = 0x01;
       }
// ОБНОВЛЕНИЕ ЭКРАНА
  if (Data_Control.upd_lcd)
     {Serial.println("Были в update_lcd");
      update_lcd(&Data_Control);
      Data_Control.upd_lcd = 0;
     }
  }
}

в цикле loop проверяется взведёный флаг факта нажатия кнопки. Нажата, отключаем Таймер_2, проверяем через switch (Data_Control.data_lcd.mode), в каком режиме мы находимся, неважно в каком режиме, по коду кнопки попадаем в определённый case X. Обработали нажатие своей функцией, выходим из SWITCH, опускаем флаг нажатой кнопки (change_butt_16), взводим флаг прохода антидребезга по отжатию кнопки (finish), включаем Таймер_2, заходим в проверку взведённого флага обновления данных на экране. Если взведён, заходим в update_lcd(&Data_Control); далее опускаем флаг Data_Control.upd_lcd. Так вот вопрос: почему, если я закомментирую case какой-нибудь (уберу обработчик нажатия определённой кнопки) и даже не нажимаю на эту кнопку, моя программа работает на ура? Я не вижу логики... Я думаю, Вы со мной согласны на этот счёт - нет обработчика, нет реакции на нажатие кнопки, так причём тут такое изменение работы программы с ошибкой (или как это назвать)? Это 1-ый момент, теперь подобный момент второй: я урезал по просьбе код, но реально, меньше не могу, так как программа в этом случае работает хорошо. Теперь следующий код (функция update_lcd();) по обновлению данных экрана который был у меня до этого:

// ************************************************************************************
void update_lcd(DATA_CONTROL *_Data_Control)
// ============================ СНАЧАЛА ОСНОВНЫЕ ПАРАМЕТРЫ ============================ 
{// ************* ВКЛ - ВЫКЛ А4988 *************
  if (_Data_Control->data_lcd.upd_enable == 1)
     {lcd.setCursor(Data_Control.data_lcd.ENABLE_X, Data_Control.data_lcd.ENABLE_Y);
      if (_Data_Control->data_lcd.enable == 1)
          lcd.print("OFF");
      else 
          lcd.print("ON ");
      _Data_Control->data_lcd.upd_enable = 0;
     }

// ************* СМЕНИМ ДАННЫЕ МИКРОШАГА *************
  if (_Data_Control->data_dvig.upd_size_step == 1)
     {lcd.setCursor(Data_Control.data_lcd.STEP_SIZE_X, Data_Control.data_lcd.STEP_SIZE_Y);
      switch (_Data_Control->data_dvig.size_step)
           {case 0: lcd.print("FULL");
                    break;
            case 1: lcd.print("1/2 ");
                    break;
            case 2: lcd.print("1/4 ");
                    break;
            case 3: lcd.print("1/8 ");
                    break;
            case 4: lcd.print("1/16");
                    break;
            default: break;
           }
      _Data_Control->data_dvig.upd_size_step = 0;
     }

// ************* ОБНОВИМ НАПРАВЛЕНИЕ *************
  if (_Data_Control->data_dvig.upd_dir == 1)
     {lcd.setCursor(Data_Control.data_lcd.DIR_X, Data_Control.data_lcd.DIR_Y);
      switch (_Data_Control->data_dvig.dir)
           {case 0: lcd.print(">>");
                    break;
            case 1: lcd.print("<<");
                    break;
            default: break;
           }
      lcd.noBlink();
      _Data_Control->data_dvig.upd_dir = 0;
     }

// ************* ОБНОВИМ СКОРОСТЬ *************
  if (_Data_Control->data_dvig.upd_rpm == 1)
   {float rpm_f;
    rpm_f = (float)_Data_Control->data_dvig.rpm / 10.0;
    lcd.setCursor(Data_Control.data_lcd.RPM_X, Data_Control.data_lcd.RPM_Y);
    lcd.print(rpm_f, 1);
    _Data_Control->data_dvig.upd_rpm = 0;
   }

// ************* ОБНОВИМ IMP от 1% до 50% *************
  if (_Data_Control->data_dvig.upd_imp_cnt == 1)
     {if (_Data_Control->data_mode_3.start_proverka_flag == 1)
          lcd.setCursor(Data_Control.data_lcd.IMP_CNT_X, Data_Control.data_lcd.IMP_CNT_Y);   
      else
          lcd.setCursor(Data_Control.data_lcd.IMP_CNT_X, Data_Control.data_lcd.IMP_CNT_Y);
      lcd.print(Data_Control.data_dvig.imp_cnt);
      if (_Data_Control->data_dvig.imp_cnt < 10)
         lcd.print("% ");
      else
         lcd.print("%");
      _Data_Control->data_dvig.upd_imp_cnt = 0;
     } 
 }

и сравнить его с последним, урезанным:

// ************************************************************************************
void update_lcd(DATA_CONTROL *_Data_Control)
// ============================ СНАЧАЛА ОСНОВНЫЕ ПАРАМЕТРЫ ============================ 
{// ************* ВКЛ - ВЫКЛ А4988 *************
  if (_Data_Control->data_lcd.upd_enable == 1)
     _Data_Control->data_lcd.upd_enable = 0;

// ************* ОБНОВИМ ДАННЫЕ МИКРОШАГА *************
  if (_Data_Control->data_dvig.upd_size_step == 1)
     _Data_Control->data_dvig.upd_size_step = 0;

// ************* ОБНОВИМ СКОРОСТЬ *************
  if (_Data_Control->data_dvig.upd_rpm == 1)
    _Data_Control->data_dvig.upd_rpm = 0;

// ************* ОБНОВИМ IMP от 1% до 50% *************
  if (_Data_Control->data_dvig.upd_imp_cnt == 1)
      _Data_Control->data_dvig.upd_imp_cnt = 0;
}

В последнем примере оставлены только флаги обновления параметров, отображаемых в экране. Что тут сказать, опишу следующую странность для меня... Смотрим на предпоследний код, когда мы заходим в update_lcd(); проверяется каждый флаг обновления параметра на экране, если он взведён, значит на экране изменяем значение параметра. Что будет, если, допустим удалим код направления вращения шаговика

// ************* ОБНОВИМ НАПРАВЛЕНИЕ *************
  if (_Data_Control->data_dvig.upd_dir == 1)
     {lcd.setCursor(Data_Control.data_lcd.DIR_X, Data_Control.data_lcd.DIR_Y);
      switch (_Data_Control->data_dvig.dir)
           {case 0: lcd.print(">>");
                    break;
            case 1: lcd.print("<<");
                    break;
            default: break;
           }
      lcd.noBlink();
      _Data_Control->data_dvig.upd_dir = 0;
     }

Ничего не будет! Флаг останется взведённым и всегда таким останется. Просто по выходу из update_lcd(); опустится флаг 

Data_Control.upd_lcd = 0;

и мы не зайдем сюда больше, пока не нажмём кнопку и не взведётся ещё какой-нибудь флаг обновления параметров. Вопрос: так почему при удалении кода одного или нескольких обработчиков флагов (допустим направления UPD_DIR, микрошага upd_size_step, скорости upd_rpm) программа отрабатывает нормально - никакого мусора в мониторе порта и отображение режима на экране происходит и даже без задержки? 

Я оставил флаги, потому что удалив их обработку (вчера постепенно урезая свой код до минимума) программа работает без проблем. Здесь я тоже никакой логики не вижу и поэтому прошу помощи! Либо я действительно не вижу ошибки в коде (и я снимаю перед Вами шляпу), либо у меня что не так с Ардуино... Не прошу теперь писать варианты почему так происходит, а реально создать скетч по моему коду и протестировать на Ардуино Мега. Можно без LCD экрана, и без клавы 4*4, смотреть в монитор порта, имитация нажатия этой проблемной кнопки (смена режима) это замыкание выводов А9 и А12. Этот порт (PORTK) подключен к клаве. Моя почта abajdin_59rus@mail.ru для более подробной связи и желательно по телефону, так как я такого мнения, что лучше подробнее и намного быстрее и экономнее в наше время объясниться по аудио. 8-912-59 54 026. Могу сам позвонить. Всем Спасибо!

b707
Онлайн
Зарегистрирован: 26.05.2017

вы вообще себя слышите?  Вы же ни разу не выложили связного кода от начала до конца - и вы просите кого-то собрать макет для проверки? Что проверять то, отдельные функции с кучей взаимопересекающихся переменных?

Отправляйтесь в платный раздел - может кто-то возьмется отлаживать ваш проект тысяч этак за 15-20... и то сомневаюсь.

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

Я могу выслать код целиком, напишите мне на почту. У меня в каждом отдельном файле *.ino описаны функции по тематике, LCD например, или отработке нажатия кнопок каждого из режимов. Я пока связанный код не знаю как сделать, пробовал, но у меня со структурами сразу же возникли сложности. Думаю, по описанным странным для меня ошибкам есть люди заинтересовавшимися в них, пусть напишут на почту, там вышлю код

 

AlexBajdin59rus
Offline
Зарегистрирован: 17.12.2019

b707 пишет:

AlexBajdin59rus пишет:

Примерно понял Вашу мысль... но я думаю, что если в относительно простом моём коде не работает, то на ещё одном дополнительном режиме всё останется по прежнему.

скажите, а зачем вы вообще сюда пишете?

Упрощать код вы не стали. любые советы отвергаете, сами ошибку тоже не ищете. С вашим настроем остается только завернутся в простыню и ползти на кладбище, шансов решить проблему у вас нет.

Я упростил код до минимума, насколько смог (Дальнейшее удаление частей кода приводит к нормальной работе, но какое-то оно хаотичное, нет определённой связи, не вижу её по описанным ошибкам). Ошибку искал, начал заново, постепенно добавил второй режим, и вот когда он уже почти весь, происходит для меня непонятная странность, вычислить причину которую не могу. Настрой реально упал, проект замер  на месте, а сейчас такая возможность кодить, пока самоизолируемся... 

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

AlexBajdin59rus, вы реально не слышите, говорю же - быстродействия скорее всего не хватает, симптомы знакомые, избавьтесь от uart совсем.