Ускоряем Arduino в 20 раз



Библиотека для разгона



Библиотека «CyberLib» даёт существенный прирост скорости (запись/чтение цифровых портов в 20 раз) и уменьшает размер используемой памяти.

Синтаксис предельно прост и будет понятен даже новичкам.

Ссылка на скачивание находится в конце статьи.

Примеры использования:

Работа с цифровыми портами
Стандартный скетч Blink без delay():

void setup()
{
   pinMode(13, OUTPUT);
}

void loop()
{
   digitalWrite(13, HIGH);
   digitalWrite(13, LOW);
}  

Занимает 874 байта и выдаёт на пин 13 частоту 120 кГц


С библиотекой «CyberLib»

#include "CyberLib.h"
void setup()
{
   D13_Out; 
}

void loop()
{
   D13_High;
   D13_Low;
}  

Занимает 566 байт и выдаёт частоту 2650 кГц


Управление пинами:

Dx_Out; — установка пина Х как выход
Dx_In; — установка пина Х как вход
Dx_Hihg; — установка высокого уровна на пине Х
Dx_Low; — установка низкого уровня на пине Х
Dx_Read; — чтение пина Х
Dx_Inv; — инвертирует значение на пине Х

Чтение аналогового входа
Стандартный скетч:

unsigned long   timme;

void setup()
{
   Serial.begin(57600);
}

void loop()
{
   timme = micros(); 
   float i = analogRead(0);
   timme = micros()-timme;
   Serial.println(timme);
   delay(1000);
} 

Скорость чтения 112 мкс


С библиотекой «CyberLib»

#include "CyberLib.h"
unsigned long   timme;
void setup()
{
   Serial.begin(57600);
}

void loop()
{
   timme = micros(); 
   float i = A0_Read;
   timme = micros()-timme;
   Serial.println(timme);
   delay(1000);
} 

Скорость чтения 68 мкс


Управление пинами:

Ax_Read; — чтение аналогового пина Х

Чтение и запись Serial
Стандартный скетч:

byte b=255;

void setup() 
 {
    Serial.begin(57600);
 }

void loop() 
 { 
    Serial.write(b);
 } 

Скетч занял 1650 байт


С библиотекой «CyberLib»

#include "CyberLib.h"
byte b=255;

void setup() 
 {
    UART_Init(57600);
 }

void loop() 
 { 
 
  if(UART_ReadByte(b)) 
   { 
      UART_SendByte(b);
   }
 }

Скетч занял 800 байт


UART_Init(57600); — инициализация последовательного порта
UART_ReadByte(b); — получить байт данных из последовательного порта
UART_SendByte(b); — отправить байт данных в последовательный порт

Буфферизируется только 1 байт данных, принятый с Serial порта

Отправка массива в Serial
#include "CyberLib.h"  
uint8_t message[] = "std"; 

void setup()  
 {   
    UART_Init(57600);
 }  
void loop()  
 {  
    UART_SendArray( message, 3); 
 } 



UART_SendArray(array, size array); — отправляет в порт массив типа байт. Где array-имя вашего массива, а size array-число отправляемых байт массива.
Максимальный объем массива не должен превышать 65535 байт

Альтернатива стандартным функциям delayMicroseconds() и delay()
Функции delay_us(); и delay_ms(); можно применять в прерываниях так как они не используют таймер.
Их точность зависит от использования в коде обработчиков прерываний. Если прерывания в коде не используются, то и точность будет высокая.
delay_us(n); n — задержка в мкс, максимальная задержка может быть не больше 16000 мкс
delay_ms(n); n — задержка в мс, максимальная задержка может быть не больше 65000 мс

Работа с Timer1
#include "CyberLib.h" 
void setup() 
{  
   D13_Out; 
   StartTimer1(obrobotchik, 1000000);  
} 

void obrobotchik() 
{ 
  D13_High; 
  delay_ms(100);
} 

void loop()
{
  D13_Low;
} 



StartTimer1(obrobotchik, 1000); Первый параметр — обработчик прерывания, запускаться каждый раз по истечении заданного времени.
Второй параметр это время, может принимать значения от 6 до 4000000 мкс, шаг 1 мкс.
StopTimer1(); — остановить таймер
ResumeTimer1(); — возобновить отсчет после остановки
RestartTimer1(); — перезапустить отсчет таймера заново

Работа с SPI
#include "CyberLib.h"
byte b=255; 
void setup() 
{  
   StartSPI(0, 8, 1); // MODE0, DIV8, MSBFIRST инициализация SPI  
} 
void loop() 
{ 
  SendSPI(b); //отправить один байт в шину SPI
}



Увеличена пропускная спсобность 1.85 раза

StartSPI(0, 2, 1); — Первый параметр это режим mode от 0 до 3.
Второй — это делитель тактовой частоты, может принимать значения 2, 4, 8, 16, 32, 64, 128.
Для вычисления частоты SPI нужно тактовую частоту контроллера 16000000 разделить на любой делитель из списка.
Третий параметр это какой бит пойдет первым. Если 1 то первым пойдет старший бит если 0 то первым пойдет младший бит.

Отправить байт: SendSPI(b);
Получить байт: MyData=ReadSPI();
Выключить SPI: StopSPI();

Работа с EEPROM
WriteEEPROM_Long(0, 4000000); — записать 4000000 в EEPROM по адресу 0 тип Long
uint32_t tmp=ReadEEPROM_Long(0); — прочитать из EEPROM с адреса 0 значение типа Long
WriteEEPROM_Word(0, 4000); — записать 4000 в EEPROM по адресу 0 тип Word
uint16_t tmp=ReadEEPROM_Word(0); — прочитать из EEPROM с адреса 0 значение типа Word
WriteEEPROM_Byte(0, 40); — записать 40 в EEPROM по адресу 0 тип Byte
uint8_t tmp=ReadEEPROM_Byte(0); — прочитать из EEPROM с адреса 0 значение типа Byte

Адресует максимум 256 адресов для типа Byte
Для Word максимум 128
Для Long максимум 64

Ограничение цикла
#include "CyberLib.h" 
void setup() 
{  
   // что-то
} 
void loop() 
{ 
  Start
  // что-то выполняется
  End
}



Start — Начало цикла
End — Конец цикла

Цикл выполняется внутри конструкции Start-End.

Фильтр для удаления шума или ложных срабатываний
#include "CyberLib.h"
uint16_t sensor[]={10, 15, 55, 999, 10, 8, 9, 11, 700, 455, 123, 999, 543, 567, 65535, 43555, 999, 10, 43, 99, 66, 987, 999, 100};
void setup() 
{
  Serial.begin(115200);
  uint16_t cm = find_similar(sensor, sizeof(sensor)/2, 0);
  Serial.println(cm, DEC);
}
 void loop() {}  

Приведенный пример показывает наиболее часто встречаемое значение 999, но если изменить третий параметр вызываемой функции с 0 на 1, то функция вернет значение 10, так как посчитает значение 9 и 11 как 10


find_similar(Array, sizeArray, range);
Array — Указатель на проверяемый массив, массив может иметь тип uint16_t или uint8_t
sizeArray — длинна массива не более 256 элементов
range — предел погрешности(отклонение) может колебаться от 0 до 127, при значении 0 функция будет искать точные копии значений.
Например: Ультразвуковой дальномер производит 5 замеров и складывает эти показания в массив, после выполнения этой функции будет возвращено наиболее вероятное измеряемое значение.


Скачать
Здесь находится автор библиотеки, Admin.

Распаковываем архив в папку с библиотеками и пользуемся.
Не забудьте прописать в скетче:

#include "CyberLib.h"



Вступайте в Telegram-группу Arduino


  • +798
  • 41071
Telegram-канал istarik

Известит Вас о новых публикациях...



Комментарии (24)

0
Добрый день.Нужна помощь, скетч. для индикации витков на ЖКИ (1602)(станок для намотки провода), просто индикация при срабатывании (2х контактов) работает счёт (1,2,3 и т.д.)+ сброс счётчика и времени. ну и хотелось бы просто секундная индикация времени работы.Ардуино+ЖКИ (1602).т.е в одной строке время (секундный счёт), а во второй счётчик оборотов (витков). надписи (англ), но хотелось бы на Русском. ЖКИ кирилицу поддерживает.
-1
Значит этот код работает?



#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

uint32_t time;

uint8_t chas = 0;
uint8_t minuta = 0;
uint8_t secunda = 0;
uint8_t col = 0; // счётчик

void setup() 
{
  time = micros();
  lcd.begin(16, 2); 
  lcd.print("OK");
  delay(2000);
}

void loop() 
{
  if((micros()-time) > 999450) 
      {  
        time = micros();
        secunda++;
        if(secunda > 59)  
         {
           secunda=0;
           minuta++;

           if(minuta > 59) 
             {
               minuta=0; 
               chas++;
               if(chas>23)  chas=0; 
             } 
         }
       
        flash; 
       }

}

  void flash() 
   {
     
     lcd.clear();
     lcd.print("COUNT ");
     lcd.print(col);
     lcd.setCursor(0, 1);
     lcd.print("TIME ");
     lcd.print(chas);
     lcd.print(":");
     lcd.print(minuta);
     lcd.print(":");
     lcd.print(secunda);
     
   }
0
На ЖКИ просто надпись (ОК) в верхней строке с лева
0
А на какие пины подключать (кнопку-датчик), кнопка (пин) сбос счётчика?
0
Время показывает или нет?
0
нет просто надпись ОК
0
Извиняюсь. опять моя ошибка. Отвлекаюсь.

Вот это будет работать.

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

uint32_t time;

uint8_t chas = 0;
uint8_t minuta = 0;
uint8_t secunda = 0;
uint8_t col = 0; // счётчик

void setup() 
{
  //Serial.begin(115200);
  time = micros();
  lcd.begin(16, 2); 
  lcd.print("OK");
  delay(2000);
}

void loop() 
{
  if((micros()-time) > 999450) 
      {  
        time = micros();
        secunda++;
        if(secunda > 59)  
         {
           secunda=0;
           minuta++;

           if(minuta > 59) 
             {
               minuta=0; 
               chas++;
               if(chas>23)  chas=0; 
             } 
         }
       
        flash(); 
       }

}

  void flash() 
   {
     
     lcd.clear();
     lcd.print("COUNT ");
     lcd.print(col);
     lcd.setCursor(0, 1);
     lcd.print("TIME ");
     lcd.print(chas);
     lcd.print(":");
     lcd.print(minuta);
     lcd.print(":");
     lcd.print(secunda);
     
     //Serial.println(secunda);
     
   }
0
0
Последний код должен работать.
0
0
Хорошо. Я думалю лучше на корпус,+подтяжка через резистор на (+), типа (0,1).Или как вам удобней сделать
+1
Значит подтягиваем D2 на (+) резюком ~20Ком, а замыкание будет на землю.

Вот код:

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

uint32_t time;

uint8_t chas = 0;
uint8_t minuta = 0;
uint8_t secunda = 0;
uint16_t col = 0; // счётчик

void setup() 
{
  //Serial.begin(115200);
  time = micros();
  attachInterrupt(0, int_on, FALLING);
  lcd.begin(16, 2); 
  lcd.print("COUNT OK");
  lcd.setCursor(0, 1);
  lcd.print("TIME OK");
  delay(2000);
}

void loop() 
{
  if((micros()-time) > 999450) 
      {  
        time = micros();
        secunda++;
        if(secunda > 59)  
         {
           secunda=0;
           minuta++;

           if(minuta > 59) 
             {
               minuta=0; 
               chas++;
               if(chas>23)  chas=0; 
             } 
         }
       
        flash(); 
       }

}

  void flash() 
   {
     
     lcd.clear();
     lcd.print("COUNT ");
     lcd.print(col);
     lcd.setCursor(0, 1);
     lcd.print("TIME ");
     lcd.print(chas);
     lcd.print(":");
     lcd.print(minuta);
     lcd.print(":");
     lcd.print(secunda);
     
     //Serial.println(secunda);
     
   }

void  int_on() 
   { 
      col++; //увеличить счетчик volatile
      
   }
0
УРА, РАБОТАЕТ!!! Вы SUPER! ЗА 5 минут. всё готово. а кнопку на какие пины подключить?, я на радостях скетч ещё не смотрел…
0
Будем последовательны.
Как у Вас будет происходить замыкание контакта счётчика, на плюс или на минус?
комментарий был удален
0
В чем может быть проблемма?
0
В чем может быть проблемма?
комментарий был удален
0
С Mega2560 работают только «цифровые» порты.
0
спасибо.
А на каких платформах всё работает?
0
Посмотрите в файле «CyberLib.h»
0
Спасибо.
0
Не за что.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.