Сильно тормозит скетч

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Доброе время суток

С ардуино работаю совсем недавно, писал как правило простые программы управления всякой ерундой, но тут появилась необходимость в GPS спидометре, ну и начитавшись форума решил собрать себе нормальный спидометр, с температурой, временем, и одометром.
Платформа UNO на Atmega328, по началу всё было отлично, программа летала, но в один день, начались тормоза, экран просто прорисовывается построчно, дико неудобно, и ни как не могу понять в чём проблема.
Большая просьба посмотреть программу и по возможности ткнуть меня носом в косяк.
Вот что мы имеем:
Ардуино как чип отдельно Atmega328P-PU(плату сделал сам, но проблема остаётся и на заводской платформе и на плате)
Сам чип работает на внутреннем генераторе на 8 МГц.
Экран LCD12864
Датчик температуры (модель не помню)
Модуль GPS ATGM336H (Выбран из-за Глонас)

скетч ниже

[code]
#include <OneWire.h>
#include <iarduino_GPS_NMEA.h>  
#include <SoftwareSerial.h>
#include <U8glib.h> 
#include "sav_button.h"
#include <EEPROM.h>
SButton button(6,50,1000,4000,200);
U8GLIB_ST7920_128X64_1X u8g(10);
//  Часы
const uint8_t rook_bitmap[] U8G_PROGMEM = { // массив, хранящий изображение. 0 – пиксель не горит, 1 – пиксель горит
  0x3c,         // 00000000 – 2-ичная кодировка 16-ричного числа
  0x4a,         // 01010101
  0x89,          // 01111111
  0x89,         // 00111110
  0xb1,         // 00111110
  0x81,         // 00111110
  0x42,         // 00111110
  0x3c           // 01111111
};
// Антенна
const uint8_t satell[] U8G_PROGMEM = { // массив, хранящий изображение. 0 – пиксель не горит, 1 – пиксель горит
  0x00,         // 00000000 – 2-ичная кодировка 16-ричного числа
  0x02,         // 01010101
  0x02,          // 01111111
  0x0a,         // 00111110
  0x0a,         // 00111110
  0x2a,         // 00111110
  0x2a,         // 00111110
  0x00           // 01111111
};
double lastlat,lastlng;  //  Для вычисления пройденного растояния
OneWire ds(8); // Создаем объект OneWire для шины 1-Wire, с помощью которого будет осуществляться работа с датчиком
static int led = 9; // Пин управления яркости экрана
static int brightness =174; // Первоначальная яркость экрана
static int but=0;  // Не используется
static int fadeAmount = 80;  // Минимальная яркость экрана
static int temp = 0; // Первоначальная температура
static int km=0; // Первоначальная скорость
static int has=0;  // Часы
static int mi=0;  // Минуты
static int xs=68;  // Положение курсора для КМ/Ч
static int alti=0;  // Выоста
static long odog=372000;  // Предыдущий пробег
static long odox=0;  // Общий пробег
static long odos=0;  // Суточый пробег
static long odot=0;  // Пробег с начала работы
static long odo=0;  // на всякий случай
static long odo1=0;
static long lat1=1;
static long lat2=1;
static long distance=0;
static long lastUpdateTime = 0; // Переменная для хранения времени последнего считывания с датчика
const int TEMP_UPDATE_TIME = 5000; // Определяем периодичность проверок
float input_volt = 0.0;
float volt=0.0;
float r1=24000.0; //сопротивление резистора r1
float r2=10000.0; // сопротивление резистора r2
unsigned long next_time; // время очередной прорисовки
int timeout = 500; // период прорисовки
static const int RXPin = 2, TXPin = 3;
static const uint32_t GPSBaud = 9600;
iarduino_GPS_NMEA    gps; 
//iarduino_GPS_ATGM336 SettingsGPS;
SoftwareSerial ss(RXPin, TXPin);
char* wd[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};   //  Определяем массив строк содержащих по две первых буквы из названий дня недели.
void setup()
{
  Serial.begin(9600);
  gps.timeZone(5);
  ss.begin(GPSBaud);
  gps.begin(ss);// Считываем данные из памяти
  EEPROM.get(0, odot);
  EEPROM.get(4, odos);
  pinMode(led, OUTPUT);  //  Определение пина для яркости
  button.begin();
  pinMode(5, INPUT);  // Вход питания
  pinMode(4, OUTPUT);  //  Упревление реле
  digitalWrite(4, HIGH);  //  Включение реле
  analogWrite(led, brightness);  //  Включение подсветки экрана
// Страница приветсвия
  u8g.firstPage();
  do{
    u8g.setRot180();
    u8g.setFont(u8g_font_8x13B);
    u8g.setPrintPos( 40, 35); u8g.print("HELLO!");
     } while(u8g.nextPage());
     delay (2000);
  next_time = millis() + timeout; // вычисляем время следующей прорисовки
  odox = odog + odot/1000;
}

void loop()
{
  detecthas();  //определине часов
  lcdscreen(); //прорисовка экрана
  detectTemperature();  // градусник
  detectkmph();  // скорость
  detectxs();  // Положение курсора КМ/Ч
  int now_time = millis(); // текущее время
  int save = digitalRead(5);  //  Сигнал подачи питания
  int analogvalue = analogRead(A0); //  Пин вольтметра
// Отрисовка экрана 1/300 сек
  if( now_time >= next_time ){ // если текущее время превысило намеченное время, то
        next_time = now_time + timeout; // вычисляем время следующего переключения
         lcdscreen();
  }
     gps.read();                                  //  Читаем данные с получением информации о спутниках в массив i (чтение может занимать больше 1 секунды). Если указать второй параметр gps.read(i,true); то в массиве окажутся данные только тех спутников, которые принимают участие в позиционировании.
// формула для конвертирования значения напряжения
   volt = (analogvalue * 5.0) / 1024.0;
   input_volt = volt / (r2/(r1+r2));
   if (input_volt < 0.1){
   input_volt=0.0;
   }
// Яркость экрана
  analogWrite(led, brightness); 
// Обработка кнопки, короткое изменение яркости, длинное сброс счётчиков
  switch( button.Loop() ){
      case SB_CLICK:
  brightness = brightness + fadeAmount;
  if (brightness == 14 || brightness == 254) {
    fadeAmount = - fadeAmount ;
   }
         break;
      case SB_LONG_CLICK:
         odos=0;
         break;
      case SB_AUTO_CLICK:
         //odox=372000;
         break;
  }
//  Определеие пройденного расстояния
       if(lastlat!=0 && lastlng!=0 && km>0)
       {
  double delta = radians((gps.longitude)-lastlng);
  double sdlong = sin(delta);
  double cdlong = cos(delta);
  lat1 = radians(gps.latitude);
  lat2 = radians(lastlat);
  double slat1 = sin(lat1);
  double clat1 = cos(lat1);
  double slat2 = sin(lat2);
  double clat2 = cos(lat2);
  delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
  delta = sq(delta);
  delta += sq(clat2 * sdlong);
  delta = sqrt(delta);
  double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
  delta = atan2(delta, denom);
  distance=delta * 6372795;
  odo=distance;
  odot+=distance;
  odos+=distance;
  odox = odog + (odot/1000);
       }
       lastlng=(gps.longitude);
       lastlat=(gps.latitude); 
  if (km>but){
    but=km;
   }

//  Наличие или отсутсвие питания    
   if (save == LOW){
         save_f();
     }
}

int detecthas(){

  has=(gps.Hours);

}

int lcdscreen(){
  u8g.firstPage();
  do{  u8g.setRot180();
       u8g.setColorIndex(1); 
       u8g.drawBitmapP( 32, 5, 1, 8, rook_bitmap);
       u8g.drawBitmapP( 105, 2, 1, 8, satell);
       u8g.setFont(u8g_font_8x13B);
       u8g.drawHLine(0, 41, 128);
       u8g.drawHLine(0, 17, 128);
       u8g.drawVLine(30, 17, 24);
       u8g.drawVLine(90, 0, 17);
       u8g.drawVLine(30, 0, 17);
       u8g.drawVLine(75, 42, 22);
       u8g.setPrintPos( 42, 14);
       u8g.drawHLine(75, 52, 63);
       u8g.drawFrame(0,0,128,64);
       if (has < 10){u8g.print(" ");
       u8g.setPrintPos( 53, 14);u8g.print(has);
       }
       else
       {
       u8g.print(has);
       }
       u8g.setPrintPos( 60, 14); u8g.print(":");
       u8g.setPrintPos( 70, 14);
       if (gps.minutes < 10){u8g.print("0");
       u8g.setPrintPos( 80, 14);u8g.print(gps.minutes);
       }
       else
       {
       u8g.print(gps.minutes);
       }
       u8g.setFont(u8g_font_6x10);
       u8g.setPrintPos( 2, 13); u8g.print(temp);
       u8g.drawCircle(21, 7, 1.5);
       u8g.drawStr(24, 13, "C");
       u8g.setFont(u8g_font_courB24n);
       u8g.setPrintPos( (xs), 40); u8g.print(km);
       u8g.setFont(u8g_font_6x10);
       u8g.setPrintPos( 8, 28); u8g.print("MAX");
       u8g.setPrintPos( 8, 39); u8g.print(but);
       u8g.setPrintPos( 93, 40); u8g.print("km/h");
       u8g.setFont(u8g_font_6x10);
       u8g.setPrintPos( 2, 51); u8g.print("ODO:");
       u8g.setPrintPos( 27, 51); u8g.print(odox);
       u8g.setPrintPos( 2, 61); u8g.print("SUT:");
       u8g.setPrintPos( 27, 61); u8g.print(odos/1000);
       u8g.setFont(u8g_font_5x8);
       u8g.setPrintPos( 114, 8); u8g.print(gps.satellites[GPS_ACTIVE]);
       u8g.setPrintPos( 104, 16); u8g.print(gps.altitude,1);
       u8g.setPrintPos( 76, 50);
       if (gps.day<10){ u8g.print("0");
       u8g.setPrintPos( 81, 50);u8g.print(gps.day);
       }
       else
       {
       u8g.print(gps.day);
       }
       u8g.setPrintPos( 86, 50); u8g.print("/");
       u8g.setPrintPos( 91, 50);
       if (gps.month<10){ u8g.print("0");
       u8g.setPrintPos( 96, 50);u8g.print(gps.month);
       }
       else
       {
       u8g.print(gps.month);
       }       
       u8g.setPrintPos( 101, 50); u8g.print("(");
       u8g.setPrintPos( 106, 50); u8g.print(wd[gps.weekday]);
       u8g.setPrintPos( 121, 50); u8g.print(")");
       u8g.setPrintPos( 83, 61); u8g.print("V");
       u8g.setPrintPos( 90, 61); u8g.print(input_volt);
       }  while(u8g.nextPage()); 
}
//  Отключение и сохранение данных
int save_f(){
  analogWrite(led, brightness);
  EEPROM.put(0, odot);
  EEPROM.put(4, odos);
  u8g.firstPage();
  do{
    u8g.setRot180();
    u8g.setFont(u8g_font_8x13B);
    u8g.setPrintPos( 20, 35); u8g.print("GOOD LUCK!");
     } while(u8g.nextPage());
     delay (2000);
     digitalWrite(4, LOW);
}
// Определие курсора  КМ/Ч
int detectxs(){
        if(km < 10){
          xs=(68);
        }          
        if(km > 9 && km < 100){
          xs=(51);
          }
        if(km > 99){
          xs=(32);
          }      
}
// Определие скорости
int detectkmph(){
   km = (gps.speed);
}
//  Определение температуры
int detectTemperature(){

  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);

  if (millis() - lastUpdateTime > TEMP_UPDATE_TIME)
  {
    lastUpdateTime = millis();
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    temp = (data[1] << 8) + data[0]; temp = temp >> 4;
  }
}
[/code]

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Если началось ни с того ни с сего, значить, у тебя на 5-м пине всегда LOW

Snowhorg
Offline
Зарегистрирован: 03.02.2022

На пятый пин по схеме приходит +5 от отдельного стабилизатора
Я вот подумал может проблема с экраном, так как он медленно рисует внутри самой функции, но до этого рисовал на ура, а другого, что бы подкинуть нет.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Snowhorg пишет:
На пятый пин по схеме приходит +5 от отдельного стабилизатора

А ты померий

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Мерил, там высокий уровень, проблема где в прорисовке, если отключить дисплей и его библиотеку, и выводить данные на "монитор порта", то всё работает быстро.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Вот схема, если интересно.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Подозреваю что с GPS летит очень много ненужных данных и контроллер постоянно занят их приёмом. Надо настроить GPS на передачу только нужных пакетов и поиграться с частотой и скоростью таких передач.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

По поводу скорости передачи данных, пробовал почти все поддерживаемые (по паспорту), но полные и нормальные данные выдаёт только на 9600, при смене скорости, то время не выдаёт, то скорость не видит, то спутники.

А вот как поменять количество данных я пока не разобрался, НО...

проблема начинается ещё до начала чтения данных с GPS, уже страница приветствия тормозит, а  " gps.read();" стоит намного ниже.

Может кто знает как проверить LCD или перешить его как-то можно.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Serial читает данные сразу после его активации. Попробуйте его пока не включать или отключите GPS физически.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Вечером попробую отключить, тем более это не проблема, ну а если действительно поможет, что делать-то дальше, я не смог разобраться в "Птичьем" языке описания протокола NMEA, не на трезвую голову ни с поллитра.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

А поможет ( как эксперимент), если я перенесу включение Serial, после страницы приветствия?

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

SoftwareSerial и 9600 - это не для спидометра. Даже если с экраном справитесь.

А по теме - выкидывайте лишнее рисование и измеряйте ускорение.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

sadman41 пишет:
SoftwareSerial и 9600 - это не для спидометра. Даже если с экраном справитесь. А по теме - выкидывайте лишнее рисование и измеряйте ускорение.

Ну со скоростью я ещё поиграю, хотя прошлые попытки мне не понравились,
а вот на счёт рисования, такая мысль приходила в голову, и даже отключал всё рисование кроме цифр, результат то-же, вечером проведу ряд экспериментов, по советам, и обязательно отпишусь.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Скорее всего придётся отключать SoftwareSerial при каждом рисовании на экране.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Komandir пишет:

Скорее всего придётся отключать SoftwareSerial при каждом рисовании на экране.

А вот с этого момента по подробнее, как его отключать и подключат обратно?

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

Пройденный этап. Для спидометра нужна высокая скорость обновления, что тащит за собой повышенную скорость порта. Где-то до 115200. Софтсериал на 38400 захлебнется. Плюс - большой оверхед на дисплее.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Не понял на счёт "Софтсериал на 38400 захлебнётся", а на 115200 нормально что-ли будет работать?
Ну экран рисуется 2 раза в секунду.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

на 115200 тем более

надо делать на аппаратном serial 

если загрузка скетчей идет через serial, то надо делать переключатель на дорожке TX и коммутировать сигналы от TX USB-UART и от TX GPS

Morroc
Offline
Зарегистрирован: 24.10.2016
093 void loop()
094 {
095  
096   lcdscreen(); //прорисовка экрана
097  
098  
099  
100  
101  
102  
103 // Отрисовка экрана 1/300 сек
104   if( now_time >= next_time ){ // если текущее время превысило намеченное время, то
105         next_time = now_time + timeout; // вычисляем время следующего переключения
106          lcdscreen();
107   }
108  

Snowhorg пишет:

Ну экран рисуется 2 раза в секунду.

Да он вроде постоянно рисуется. Верхний вызов лишний ?

Snowhorg
Offline
Зарегистрирован: 03.02.2022

На аппаратном Serial, это 0 и 1 (RX,TX), если я правильно понял, переделать не сложно, они у меня свободные, а прошить могу и через программатор USBAsp.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Snowhorg пишет:

 прошить могу и через программатор USBAsp.

Тем более нет смысла в softserial

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Упс, просмотрел, раньше рисовался постоянно.
Вот СПАСИБО!!!!!

 

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Komandir пишет:

Snowhorg пишет:

 прошить могу и через программатор USBAsp.

Тем более нет смысла в softserial

\

просто сериал прописать?

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Конструкцией типа if( now_time >= next_time ) я бы пользоваться не советовал. Во избежании так сказать...

Лучше использовать if( now_time - last_time >= timeout) { last_time = now_time ;

И вопрос - а зачем все подпрограммы у Вас int? Вы же ничего не возвращаете.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

mykaida пишет:

Конструкцией типа if( now_time >= next_time ) я бы пользоваться не советовал. Во избежании так сказать...

Лучше использовать if( now_time - last_time >= timeout) { last_time = now_time ;

И вопрос - а зачем все подпрограммы у Вас int? Вы же ничего не возвращаете.

Спасибо за совет, но я не понял принципиальной разницы в условии.
Может есть какие "подводные камни" в моём условии, поясните если не трудно.

На счёт "int", старая дурацкая привычка, ни как не отучусь, хорошо хоть "Return" перестал вписывать ))))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Snowhorg пишет:

Спасибо за совет, но я не понял принципиальной разницы в условии.

Может есть какие "подводные камни" в моём условии, поясните если не трудно.

Почитай за переполнение миллис.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

BOOM пишет:

Snowhorg пишет:

Спасибо за совет, но я не понял принципиальной разницы в условии.

Может есть какие "подводные камни" в моём условии, поясните если не трудно.

Почитай за переполнение миллис.

Спасибо за наводку, прочитал, код исправлю

 

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Коллеги
Воспользовавшись советами в ветке, вчера внёс изменения, а именно:
1 Уменьшил количество данных с GPS до одной строки NMEA_RMC, правда пришлось пожертвовать информацией о спутниках, да и ладно.
2 Спасибо Morroc, указал на косяк в прорисовке, косяк исправлен.
3 Все попытки получить данные по Serial ни к чему не привели, судя по светодиоду данные приходят, но на мониторе порта тишина, перепробовал все методы какие нашёл, пришлось вернуться на SoftSerial, поднял частоту до 57600, пока ошибок или пробелов не было
4 Ну и убрал лишнюю графику с экрана

Промежуточный итог, скорость работы и прорисовки выросла до нормальной, осталось исправить код прорисовки.
Но вот гложет момент с Serial, проверял на разных платформах (2 UNO, 1 Nano168), результат один, светодиод мигает, данных нет.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Дорожку от RX к микросхеме USB-UART надо перерезать - потому что иначе конфликт между TXами !

Приём должен идти от GPS, а вывод в USB ... (управлять GPS при таком соединении не получится)

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

Проще взять Pro Mini вместо Nano, чем резать. 

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Komandir пишет:

Дорожку от RX к микросхеме USB-UART надо перерезать - потому что иначе конфликт между TXами !

Приём должен идти от GPS, а вывод в USB ... (управлять GPS при таком соединении не получится)

Спасибо вечером попробую ещё раз,
уточню, от 2 вывода отрезать дорожку на контроллер USB, и оставить только ту, что идет на пин?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

sadman41 так ТС зачем то монитор порта нужен ...

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Snowhorg я не знаю как именно разведены дорожки на вашем экземпляре ! Оптимально резать рядом с микросхемой USB-UART.

Главное что бы на RX приходил сигнал только с GPS ! Иначе это КЗ когда на TX ах разные уровни сигнала !

 

Вы так и не написали что тормозило вывод !?

Snowhorg
Offline
Зарегистрирован: 03.02.2022

sadman41 пишет:

Проще взять Pro Mini вместо Nano, чем резать. 

У меня вся схема работает на отдельной плате, там нет контроллера USB, но отладка кода и проверка проходит на платформе, для удобства и контроля.
Есть одна UNO которую не жалко, вот там и отрежу, она как программатор для чипов у меня используется.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Komandir пишет:

sadman41 так ТС зачем то монитор порта нужен ...

Монитор порта нужен только во время отладки, потом чип вообще снимается с платформы и помещается в плату. Но с платы монитора не видно, и пойди пойми что там происходит.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Komandir пишет:

Вы так и не написали что тормозило вывод !?

 

Судя по всему количество данных с датчика GPS, там было максимум строк

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

В итоговом скетче вообще отключите вывод в монитор порта - если эти данные попадут в GPS - не факт что они его не "нагнут" !!!

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Komandir пишет:

В итоговом скетче вообще отключите вывод в монитор порта - если эти данные попадут в GPS - не факт что они его не "нагнут" !!!

Ну это понятно, я стираю всё что связано с выводом на монитор, нафиг и так программа не маленькая.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Вы столкнулись с особенностью работы SoftwareSerial - работа скетча прерывается по приходу стартового бита и восстанавливается после только после получения всего байта. Если байты идут один за другим, то скетч простаивает 90+% времени. На скорости 9600 - за секунду можно принять всего 960 байт. Сколько байт отсылал ваш GPS модуль по умолчанию мне не известно, но явно больше чем вам было нужно для получения необходимых данных.

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

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

 

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

Komandir пишет:

На скорости 9600 - за секунду можно принять всего 960 байт. Сколько байт отсылал ваш GPS модуль по умолчанию мне не известно, но явно больше чем вам было нужно для получения необходимых данных.

Тут ещё вопрос в Update Rate. Если бахнуть 10Hz, то вообще прёт как из поливочного шланга.  Всё, конечно, от задачи зависит, но на стандартном 1Hz спидометр на велосипед можно ставить, как мне кажется. 

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Ну у меня и стоит 10 Hz, правда в описании библиотека написано, что read() читает данные в 2 раза меньше чем передаёт чип, по этому 10 и поставил.
Ставиться спидометр будет на машину, родной помер без возвратно, восстановление стоит очень дорого, нужно коробку полностью разбирать, и по большому спидометр нужен больше ради одометра, скорость я и так мерить умею, по оборотам ))))

Snowhorg
Offline
Зарегистрирован: 03.02.2022

sadman41 пишет:

 портить дорогой (нынче) товар - тоже.

Думаю перемычку поставить, надо замкнул, не надо разомкнул )

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

C аппаратным Serial основной скетч прерывался бы на доли процента для перемещения аппаратно-принятого байта в буфер и ТС мог и не столкнуться с проблемой отрисовки.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Открыл схему UNO (да думаю во многих так), так вот там на RX-TX стоят 2 резистора, попробую их поменять на диоды в правильном направлении, тогда данные (которые всегда 0 или 1, где 1 это по любому +) будут доходить до чипа, но не будут уходить в контроллер, и от контроллера будут свободно проходить до чипа.
вот схема, если я не первый кто так решил сделать опишите, получилось или нет?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

они еще и к питанию подтянуты

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Насколько Вам часто нужны данные?

Человеческий глаз, как говорят, воспринимает 25 кадров в секунду (пиктят - 24 кадра)

Вот зачем Вам опрашивать датчики быстрее этого? Вы делаете ИИ?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

mykaida пишет:

Насколько Вам часто нужны данные?

Человеческий глаз, как говорят, воспринимает 25 кадров в секунду (пиктят - 24 кадра)

Вот зачем Вам опрашивать датчики быстрее этого? Вы делаете ИИ?

Вообще-то человеческий глаз легко воспринимает и 60-85 кадров в секунду.

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

rkit
Offline
Зарегистрирован: 23.11.2016

mykaida пишет:

Человеческий глаз, как говорят, воспринимает 25 кадров в секунду (пиктят - 24 кадра)

Глаз воспринимает отдельные фотоны.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

А зачем вообще подняли тему FPS ? В коде нет речи даже про 4 FPS.

Snowhorg
Offline
Зарегистрирован: 03.02.2022

Итак, обратив внимание на  все советы и замечания по моему проекту, я внёс изменения в код.
Отрисовка больше не тормозит
Serial таки запустить удалось (без обрезки дорожек на платформе, но тема с диодами пока не закрыта)
Теперь отрисовка каждые 300 millis, скорость обмена 115200.
Мало того, сегодня были проведены "ходовые" испытания, ездил на родник.

Итог, всё отлично,
скорость показывает
расстояние считает, 
ну и т.д. и т.п.

Всем большое спасибо за помощь!
Надеюсь на дальнейшее сотрудничество.

на всякий случай ниже код скетча
 


#include <OneWire.h>
#include <iarduino_GPS_NMEA.h>  
#include <U8glib.h> 
#include "sav_button.h"
#include <EEPROM.h>
#include <iarduino_GPS_ATGM336.h> 
SButton button(6,50,1000,4000,200);
U8GLIB_ST7920_128X64_1X u8g(10);
//  Часы
const uint8_t rook_bitmap[] U8G_PROGMEM = { // массив, хранящий изображение. 0 – пиксель не горит, 1 – пиксель горит
  0x3c,         // 00000000 – 2-ичная кодировка 16-ричного числа
  0x4a,         // 01010101
  0x89,          // 01111111
  0x89,         // 00111110
  0xb1,         // 00111110
  0x81,         // 00111110
  0x42,         // 00111110
  0x3c           // 01111111
};

double lastlat,lastlng;  //  Для вычисления пройденного растояния
OneWire ds(8); // Создаем объект OneWire для шины 1-Wire, с помощью которого будет осуществляться работа с датчиком
static int led = 9; // Пин управления яркости экрана
static int brightness =174; // Первоначальная яркость экрана
static int but=0;  // Не используется
static int fadeAmount = 80;  // Минимальная яркость экрана
static int temp = 0; // Первоначальная температура
static int km=0; // Первоначальная скорость
static int has=0;  // Часы
static int mi=0;  // Минуты
static int xs=68;  // Положение курсора для КМ/Ч
static int alti=0;  // Выоста
static long odog=372000;  // Предыдущий пробег
static long odox=0;  // Общий пробег
static long odos=0;  // Суточый пробег
static long odot=0;  // Пробег с начала работы
static long odo=0;  // на всякий случай
static long odo1=0;
static long lat1=1;
static long lat2=1;
static long hp=0;
static long mp=0;
static long distance=0;
static long lastUpdateTime = 0; // Переменная для хранения времени последнего считывания с датчика
const int TEMP_UPDATE_TIME = 5000; // Определяем периодичность проверок
float input_volt = 0.0;
float volt=0.0;
float r1=24000.0; //сопротивление резистора r1
float r2=10000.0; // сопротивление резистора r2
unsigned long last_time; // время очередной прорисовки
int timeout = 300; // период прорисовки
iarduino_GPS_NMEA    gps; 
iarduino_GPS_ATGM336 SettingsGPS;
char* wd[]={" ","Jan","Febr","Mart","April","May","June","July","Augu","Sept","Octo","Nove","Dece"};   //  Определяем массив строк содержащих по две первых буквы из названий дня недели.

void setup()
{
// Считываем данные из памяти
  EEPROM.get(0, odot);
  EEPROM.get(4, odos);
  pinMode(led, OUTPUT);  //  Определение пина для яркости
  button.begin();
  pinMode(5, INPUT);  // Вход питания
  pinMode(4, OUTPUT);  //  Упревление реле
  digitalWrite(4, HIGH);  //  Включение реле
  analogWrite(led, brightness);  //  Включение подсветки экрана
// Страница приветсвия
  u8g.firstPage();
  do{
    u8g.setRot180();
    u8g.setFont(u8g_font_8x13B);
    u8g.setPrintPos( 40, 35); u8g.print("HELLO!");
     } while(u8g.nextPage());
     delay (1000);
  last_time = timeout; // вычисляем время следующей прорисовки
  odox = odog + odot/1000;
  Serial.begin(115200);                           //  Инициируем работу с аппаратной шиной UART для вывода данных в монитор последовательного порта на скорости 9600 бит/сек.
  SettingsGPS.begin(Serial);
  gps.begin(Serial);                         //  Инициируем расшифровку строк NMEA указав объект используемой шины UART (вместо программной шины, можно указывать аппаратные: Serial, Serial1, Serial2, Serial3).
  gps.timeZone(5);
}

void loop()
{
  hp=millis()/3600000;
  mp=millis()/60000;
  detecthas();  //определине часов
  detectTemperature();  // градусник
  detectkmph();  // скорость
  detectxs();  // Положение курсора КМ/Ч
  int now_time = millis(); // текущее время
  int save = digitalRead(5);  //  Сигнал подачи питания
  int analogvalue = analogRead(A0); //  Пин вольтметра
// Отрисовка экрана 1/300 сек
  if( now_time - last_time >= timeout ){ // если текущее время превысило намеченное время, то
        last_time = now_time; // вычисляем время следующего переключения
         lcdscreen();
  }
     gps.read();                                  //  Читаем данные с получением информации о спутниках в массив i (чтение может занимать больше 1 секунды). Если указать второй параметр gps.read(i,true); то в массиве окажутся данные только тех спутников, которые принимают участие в позиционировании.
// формула для конвертирования значения напряжения
   volt = (analogvalue * 5.0) / 1024.0;
   input_volt = volt / (r2/(r1+r2));
   if (input_volt < 0.1){
   input_volt=0.0;
   }
// Яркость экрана
  analogWrite(led, brightness); 
// Обработка кнопки, короткое изменение яркости, длинное сброс счётчиков
  switch( button.Loop() ){
      case SB_CLICK:
  brightness = brightness + fadeAmount;
  if (brightness == 14 || brightness == 254) {
    fadeAmount = - fadeAmount ;
   }
         break;
      case SB_LONG_CLICK:
         odos=0;
         break;
      case SB_AUTO_CLICK:
         //odox=372000;
         break;
  }
//  Определеие пройденного расстояния
       if(lastlat!=0 && lastlng!=0 && km>0)
       {
  double delta = radians((gps.longitude)-lastlng);
  double sdlong = sin(delta);
  double cdlong = cos(delta);
  lat1 = radians(gps.latitude);
  lat2 = radians(lastlat);
  double slat1 = sin(lat1);
  double clat1 = cos(lat1);
  double slat2 = sin(lat2);
  double clat2 = cos(lat2);
  delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
  delta = sq(delta);
  delta += sq(clat2 * sdlong);
  delta = sqrt(delta);
  double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
  delta = atan2(delta, denom);
  distance=delta * 6372795;
  odo=distance;
  odot+=distance;
  odos+=distance;
  odox = odog + (odot/1000);
       }
       lastlng=(gps.longitude);
       lastlat=(gps.latitude); 
  if (km>but){
    but=km;
   }

//  Наличие или отсутсвие питания    
   if (save == LOW){
       save_f();
     }
}

int detecthas(){

  has=(gps.Hours);

}

int lcdscreen(){
  u8g.firstPage();
  do{  u8g.setRot180();
       u8g.setColorIndex(1); 
       if(gps.latitude != 0){
       u8g.drawBitmapP( 32, 5, 1, 8, rook_bitmap);
       }
       u8g.setFont(u8g_font_8x13B);
       u8g.drawHLine(0, 41, 128);
       u8g.drawHLine(0, 17, 128);
       u8g.drawVLine(30, 17, 24);
       u8g.drawVLine(90, 0, 17);
       u8g.drawVLine(30, 0, 17);
       u8g.drawVLine(75, 42, 22);
       u8g.setPrintPos( 42, 14);
       u8g.drawHLine(75, 52, 63);
       u8g.drawFrame(0,0,128,64);
       if (has < 10){u8g.print(" ");
       u8g.setPrintPos( 53, 14);u8g.print(has);
       }
       else
       {
       u8g.print(has);
       }
       u8g.setPrintPos( 60, 14); u8g.print(":");
       u8g.setPrintPos( 70, 14);
       if (gps.minutes < 10){u8g.print("0");
       u8g.setPrintPos( 80, 14);u8g.print(gps.minutes);
       }
       else
       {
       u8g.print(gps.minutes);
       }
       u8g.setFont(u8g_font_6x10);
       u8g.setPrintPos( 2, 13); u8g.print(temp);
       u8g.drawCircle(21, 7, 1.5);
       u8g.drawStr(24, 13, "C");
       u8g.setPrintPos( 95, 13);u8g.print(hp);
       u8g.setPrintPos( 103, 12);u8g.print(":");
       if (mp < 10){u8g.setPrintPos( 110, 13);u8g.print("0");
       u8g.setPrintPos( 117, 13);u8g.print(mp);
       }
       else
       {
       u8g.setPrintPos( 110, 13);u8g.print(mp);
       }     
       u8g.setFont(u8g_font_courB24n);
       u8g.setPrintPos( (xs), 40); u8g.print(km);
       u8g.setFont(u8g_font_6x10);
       u8g.setPrintPos( 8, 28); u8g.print("MAX");
       u8g.setPrintPos( 8, 39); u8g.print(but);
       u8g.setPrintPos( 93, 40); u8g.print("km/h");
       u8g.setFont(u8g_font_6x10);
       u8g.setPrintPos( 2, 51); u8g.print("ODO:");
       u8g.setPrintPos( 27, 51); u8g.print(odox);
       u8g.setPrintPos( 2, 61); u8g.print("SUT:");
       u8g.setPrintPos( 27, 61); u8g.print(odos/1000);
       u8g.setFont(u8g_font_5x8);
       u8g.setPrintPos( 77, 50);
       if (gps.day<10){ u8g.print("0");
       u8g.setPrintPos( 81, 50);u8g.print(gps.day);
       }
       else
       {
       u8g.print(gps.day);
       }
       u8g.setPrintPos( 91, 50); u8g.print("/");
       u8g.setPrintPos( 98, 50);u8g.print(wd[gps.month]);      
       u8g.setPrintPos( 83, 61); u8g.print("V");
       u8g.setPrintPos( 90, 61); u8g.print(input_volt);
       }  while(u8g.nextPage()); 
}
//  Отключение и сохранение данных
int save_f(){
  analogWrite(led, brightness);
  EEPROM.put(0, odot);
  EEPROM.put(4, odos);
  u8g.firstPage();
  do{
    u8g.setRot180();
    u8g.setFont(u8g_font_8x13B);
    u8g.setPrintPos( 20, 35); u8g.print("GOOD LUCK!");
     } while(u8g.nextPage());
     delay (1000);
     digitalWrite(4, LOW);
}
// Определие курсора  КМ/Ч
int detectxs(){
        if(km < 10){
          xs=(68);
        }          
        if(km > 9 && km < 100){
          xs=(51);
          }
        if(km > 99){
          xs=(32);
          }      
}
// Определие скорости
int detectkmph(){
   km = (gps.speed);
}
//  Определение температуры
int detectTemperature(){

  byte data[2];
  ds.reset();
  ds.write(0xCC);
  ds.write(0x44);

  if (millis() - lastUpdateTime > TEMP_UPDATE_TIME)
  {
    lastUpdateTime = millis();
    ds.reset();
    ds.write(0xCC);
    ds.write(0xBE);
    data[0] = ds.read();
    data[1] = ds.read();
    temp = (data[1] << 8) + data[0]; temp = temp >> 4;
  }
}