Всем привет! мне нужно сделать поворотное устройство для небольшой антенны , чтоб по азимуту и элевации и управлять с пульта. Столкнулся с такой проблемой ,что программа на ардуино выполняется очень медленно. Я в програмировании еще лох, поэтому ума не дам что нетак, до этого что я делал таких проблем не было даже если куча библиоте подключал и создавал много переменных всегда все работало отлично, ардуину пробованл менять думал может с кварцом прблема, но не помогло. В проекте я использую Arduino nano, OLED 1,3 i2c , nrf24l01. в кочестве датчиков угла поворота два потенциометра. Проблема именно с пультом, после того как подключил библиотеку U8GLIB и нарисовал графику программа цикл проходит примерно за 100мс сужу по морганию диода при отправке в порт, а если начинаю массив перадавать по радио то вообще еще раз в 10 медленее и все лагает, ужас какой то, помогите разобраца я недавно ардуиной занялся. данные с ацп у меня в коде не 0-1023 так как при усреднении часть значений терялась до примерно 1018, подбирал экспериментально. На приемной стороне сервы 0-270 25кг к приемной стороне притензий нет. Код (C++): #include "U8glib.h" U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); //SDA_A4; SCL_A5; I2C / TWI 1.3" #include <SPI.h> #include <nRF24L01.h> #include <RF24.h> int data[2]; //массив для хранения и передачи данных const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба" RF24 radio(9, 10); // CE, CSN const byte averageFactor = 5; // коэффициент сглаживания показаний // чем выше, тем больше "инерционность" int bat = 0; // переменная батареи фильтрованных значений АЦП float volt; // переменная для напряжения батареи int asimut; int elevation; void setup() { radio.begin(); delay(2); radio.setChannel(9); // канал (0-127) radio.setDataRate(RF24_1MBPS); // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS // RF24_250KBPS на nRF24L01 (без +) неработает. // меньше скорость, выше чувствительность приемника. radio.setPALevel(RF24_PA_MIN); // мощьность передатчика, RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM, radio.openWritingPipe(pipe); // открываем трубу на передач u8g.setFont(u8g_font_8x13); //шрифт } void loop() { int elevation_lcd; int asimut_lcd; int asimut_grad; int elevation_grad; //ЭЛЕВАЦИЯ ВЫЧИСЛЕНИЯ_______________________________ elevation = (elevation * (averageFactor - 1) + analogRead(1)) / averageFactor; // ФИЛЬТРАЦИЯ ЗНАЧЕНИЙ АЦП elevation_lcd = map(elevation, 0, 1018, 0, 124); // вычисление координат указателя elevation_grad = map(elevation, 0, 1018, 0, 90); // вычисление градусов //АЗИМУТ ВЫЧИСЛЕНИЯ_______________________________ asimut = (asimut * (averageFactor - 1) + analogRead(2)) / averageFactor; // ФИЛЬТРАЦИЯ ЗНАЧЕНИЙ АЦП asimut_lcd = map(asimut, 0, 1018, 0, 124); // вычисление координат указателя asimut_grad = map(asimut, 0, 1018, -135, 135); // вычисление градусов //БАТАРЕЯ ВЫЧИСЛЕНИЯ_______________________________ bat = (bat * (averageFactor - 1) + analogRead(3)) / averageFactor; // ФИЛЬТРАЦИЯ ЗНАЧЕНИЙ АЦП volt = bat / 196; // вычисление напряжения //ПЕРЕДАЧА ДАННЫХ_______________________________________ //data[0] = analogRead(1); // фильтрованые значение в массив //data[1] = analogRead(2); // фильтрованые значение в массив //radio.write(&data, sizeof(data)); // отправляем данные и указываем сколько байт пакет //__________________________________________________________ u8g.firstPage(); // начало вывода на дисплей do { //ЭЛЕВАЦИЯ ВЫВОД НА ДИСПЛЕЙ____________________________________________ u8g.drawBox(elevation_lcd, 20, 4, 4); // укозатель u8g.drawRFrame(0, 18, 128, 8, 1); // шкала u8g.drawLine(64, 19, 64, 24); // шкала u8g.drawLine(32, 23, 32, 24); // шкала u8g.drawLine(96, 23, 96, 24); // шкала u8g.setPrintPos(0, 13); u8g.print("ELEVATION"); u8g.setPrintPos(85, 13); u8g.print(elevation_grad); //вывод градусов //АСИМУТ ВЫВОД НА ДИСПЛЕЙ____________________________________________ u8g.setPrintPos(0, 39); u8g.print("ASIMUT"); u8g.drawRFrame(0, 43, 128, 8, 1); // шкала u8g.drawLine(64, 43, 64, 49); // шкала u8g.drawLine(22, 43, 22, 49); // шкала u8g.drawLine(106, 43, 106, 49); // шкала u8g.drawLine(43, 48, 43, 49); // шкала u8g.drawLine(85, 48, 85, 49); // шкала u8g.setPrintPos(64, 39); u8g.print(asimut_grad); // вывод градусов u8g.drawBox(asimut_lcd, 45, 4, 4); // указатель //БАТАРЕЯ ВЫВОД НА ДИСПЛЕЙ____________________________________________ u8g.drawRFrame(0, 55, 15, 8, 1); //значек батареи u8g.drawFrame(14,57,3,4); //значек батареи u8g.drawBox(2, 57, 3, 4); //значек батареи u8g.drawBox(6, 57, 3, 4); //значек батареи u8g.drawBox(10, 57, 3, 4); //значек батареи u8g.setPrintPos(22, 64); u8g.print("RX"); u8g.setPrintPos(70, 64); u8g.print("TX"); u8g.setPrintPos(42, 64); u8g.print(volt, 1); //ЗНАК АНТЕННЫ____________________________________________ u8g.drawLine(127, 4, 127, 12); u8g.drawLine(125, 6, 125, 12); u8g.drawLine(123, 8, 123, 12); u8g.drawLine(121, 10, 121, 12); u8g.drawLine(119, 12, 119, 12); //_____________________________________________________ } while( u8g.nextPage() ); //конец вывода на дисплей }
Экран I2C? Меняй на SPI. А вообще ответ очевиден - никогда из конструктора майбах не получится. Только коляска Серпуховича. Поэтому полный отказ от абдурино библиотек и кода и переход на нативное программирование. Возможно, что придётся сменить кварц на максимальную частоту для МК.
Тормоза явно с выводом на экран. Хрен знает как библиотека работает, может быть она сама не оптимальная. А вообще, зачем обновлять изображение слишком часто? Может делать картинку раз в секунду, а остальное постоянно? Как вариант, вывести задачу отрисовки на отдельный МК, тогда главный будет работать быстро, а тупить "видеокарта".
Разрешение экрана 128*64 = 8192 Интерфейс i2c, частота 100кГц. В i2c каждый 8й байт накладной, значит эффективная частота 100000/8*7 = 87500. Итого только на передачу одного кадра уходит 8192/87500 = 0,09с., а этот кадр еще нужно нарисовать.
Ага, особенно библиотечные функции с незнакомым содержимым и с ожиданием ответа от периферии. Как самолет будет вообще все. Сбитый.
В примере ТС именно так все и происходит. Да и не для того прерывания, чтобы ускорять или камень разгружать.
Чтобы эффективно писать программы для дохлых МК, необходимо хорошо знать архитектуру МК и происходящие внутри процессы. Если нет - то берём малинку - малинка все стерпит.
От перестановки слагаемых сумма не меняется. Если МК может делать Н-тактов в секунду, больше он не сделает хоть с прерываниями, хоть нет. Главное уметь выкинуть лишнее, а лучше изначально не добавлять. В примере ТС ускорять перерисовкой не постоянно, а раз в какое-то время и не весь экран целиком, а там где он меняется, как советовали выше. Ну, или выделять отдельный МК для экранчика.
Совсем не меняется: например, опрашивать в прерывании кнопки или опрос тех же кнопок с использованием всеми любимой функции delay()