Espshell : отладочный инструментарий для ESP32

В Ардуино УНО и далее в ленту. Вот пример скетча авторов Glediator, немцы вроде. Это программа для ПК и матриц на WS2812b.


//##############################################################################
//##############################################################################
//                                                                             #
// Glediator to WS2812 pixel converter                                         #
// by R. Heller                                                                #
// V 1.0 - 07.01.2014                                                          #            
// wwww.SolderLab.de                                                           #
//                                                                             #
// Receives serial data in Glediator protocol format @ 1 MBit/s                #
// and distributes it to a connectect chain of WS2812 pixels                   #
//                                                                             #
// Adjust the correct DATA PIN and the correct NUMBER OF PIXELS you are using  # 
// in the definitions section below before uploading this sketch to your       #
// Arduino device.                                                             #
//                                                                             #
// Maxiumim number of supported pixeles is 512 !!!                             #
//                                                                             #
// In the Glediator software set output mode to "Glediator_Protocol",          #
// color order to "GRB" and baud rate to "1000000"                             #
//                                                                             #
//##############################################################################
//##############################################################################


//##############################################################################
//                                                                             #
// Definitions --> Make changes ONLY HERE                                      #
//                                                                             #
// To find out the correct port, ddr and pin name when you just know the       #
// Arduino's digital pin number just google for "Arduino pin mapping".         #
// In the present example digital Pin 6 is used which corresponds to "PORTD",  #
// "DDRD" and "6", respectively.                                               #
//                                                                             #
//##############################################################################

#define DATA_PORT          PORTD
#define DATA_DDR           DDRD						
#define DATA_PIN           6							
#define NUMBER_OF_PIXELS   256


//##############################################################################
//                                                                             #
// Variables                                                                   #
//                                                                             #
//##############################################################################

unsigned char display_buffer[NUMBER_OF_PIXELS * 3];
static unsigned char *ptr;
static unsigned int pos = 0;

volatile unsigned char go = 0;


//##############################################################################
//                                                                             #
// Setup                                                                       #
//                                                                             #
//##############################################################################

void setup()
{
  // Set data pin as output
  DATA_DDR |= (1 << DATA_PIN);
  
  // Initialize UART
  UCSR0A |= (1<<U2X0);                                
  UCSR0B |= (1<<RXEN0)  | (1<<TXEN0) | (1<<RXCIE0);   
  UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00)             ; 
  UBRR0H = 0;
  UBRR0L = 1; //Baud Rate 1 MBit (at F_CPU = 16MHz)
  
  ptr=display_buffer;
  
  //Enable global interrupts
  sei();
}


//##############################################################################
//                                                                             #
// Main loop                                                                   #
//                                                                             #
//##############################################################################

void loop()
{  	
  if (go==1) 
  {
    cli();
    ws2812_sendarray(display_buffer, NUMBER_OF_PIXELS * 3); 
    sei();
    go=0;
  }
}


//##############################################################################
//                                                                             #
// UART-Interrupt-Prozedur (called every time one byte is compeltely received) #
//                                                                             #
//##############################################################################

ISR(USART_RX_vect) 
{
  unsigned char b;
  b=UDR0;
  
  if (b == 1)  {pos=0; ptr=display_buffer; return;}    
  if (pos == (NUMBER_OF_PIXELS*3)) {} else {*ptr=b; ptr++; pos++;}  
  if (pos == ((NUMBER_OF_PIXELS*3)-1)) {go=1;}
}


//##############################################################################
//                                                                             #
// WS2812 output routine                                                       #
// Extracted from a ligh weight WS2812 lib by Tim (cpldcpu@gmail.com)          #
// Found on wwww.microcontroller.net                                           #
// Requires F_CPU = 16MHz                                                      #
//                                                                             #
//##############################################################################

void ws2812_sendarray(uint8_t *data,uint16_t datlen)
{
  uint8_t curbyte,ctr,masklo;
  uint8_t maskhi = _BV(DATA_PIN);
  masklo =~ maskhi & DATA_PORT;
  maskhi |= DATA_PORT;

  while (datlen--) 
  {
    curbyte = *data++;

    asm volatile
    (
      "		ldi %0,8	\n\t"		// 0
      "loop%=:out %2, %3	\n\t"		// 1
      "lsl	%1		\n\t"		// 2
      "dec	%0		\n\t"		// 3
      "		rjmp .+0	\n\t"		// 5
      "		brcs .+2	\n\t"		// 6l / 7h
      "		out %2,%4	\n\t"		// 7l / -
      "		rjmp .+0	\n\t"		// 9
      "		nop		\n\t"		// 10
      "		out %2,%4	\n\t"		// 11
      "		breq end%=	\n\t"		// 12      nt. 13 taken
      "		rjmp .+0	\n\t"		// 14
      "		rjmp .+0	\n\t"		// 16
      "		rjmp .+0	\n\t"		// 18
      "		rjmp loop%=	\n\t"		// 20
      "end%=:			\n\t" 
      :	"=&d" (ctr)
      :	"r" (curbyte), "I" (_SFR_IO_ADDR(DATA_PORT)), "r" (maskhi), "r" (masklo)
    );
  }

}


//##############################################################################
//                                                                             #
// End of program                                                              #
//                                                                             #
//##############################################################################


Непонятно почему ограничение на 512 пикселей (видимо с порта в ленту тоже не может :). Данные какие шлёт и протокол тоже не знаю, но идея ПК + УНО + матрица хорошая

если я укажу так #define NUMBER_OF_PIXELS 1024
Глобальные переменные используют 3086 байт (150%) динамической памяти, оставляя -1038 байт для локальных переменных. Максимум: 2048 байт.

если укажу 512 то вот
Скетч использует 708 байт (2%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1550 байт (75%) динамической памяти, оставляя 498 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.

это на ардуино уно, надо брать esp32…

Щас, дождусь свою матрицу, поиграться.

А софтинка для ПК-то платная, поди?

Насколько я понял, ты хочешь, чтобы ПК по RS23 отправлял в твой UNO , в евойный UART, поток команд каких-то. Которые команды твой уно будет первращать в поток импульсов для светоматрицы?

PC:USART—>UART:Arduino:GPIO—>LED Strip ?

Их недавнего:
Задачки можно просматривать. И свои и системные. Менять приоритет, удалять, ставить на паузу.

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

Это всё уже проходил. Мне не надо сейчас. Тебе предлагал по аналогии.
:slight_smile:
…и узоры не узоры и гледиатор не в ноздрю.

здесь тоже немного про отладку ESP

1 лайк

Потихоньку доделываю условные операции.

Выглядит это так (команды шелла):

if rising 5 low 6 high 7 exec my_script” - если пин 5 перешел из низкого в высокое состояние, и, к тому же, пин 6 был LOW, а пин 7 - HIGH - выполнить скрипт my_script

Или такое:

if low 5 high 6 poll 1 hour max-exec 10 exec my_script

Проверять пины 5 и 6 каждый час. Если пин 5 будет low, а пин 6 - high, то исполнить скрипт my_script. Но максимум 10 исполнений

Или такоэ:

if falling 5 rate-limit 1234 exec my_script” - если упал пятый пин, то исполнить скрипт my_script, но ограничить частоту исполнения - не чаще одного раза в 1234 миллисекунды.

Все эти ключевые слова можно комбинировать как вздумается.

Скрипт - это просто набор команд. Создаются и редактируются такие скрипты прямо в шелле.

Из реальных применений - ну вот у меня контроль за наполняемостью бака сделан целиком на шелле. Мотор помпы включает\выключает. Пытается лаже с нештатными ситуациями бороться.

Так же в процессе операции переодические. Выглядит это так:

every 3 hour exec my_script” - запускать скрпит каждые три часа. первое исполние произойдет сразу по выполнении данной команды

every 10 sec delay 3 days max-exec 666 exec my_script” - каждые 10 секунд, но отсрочить первое выполнение на три дня, выключить условие через 666*10 секунд.

Написано иначе:
Если пин 5 будет low, а пин 6 - high, проверять каждый час.

Только при различных комбинациях получается различный смысл.

Чтобы избежать неоднозначности, люди придумали два варианта:

  • строгий порядок действий, например, слева направо без учета приоритетов операций,
  • скобки.

Синтаксис такой, можно, одинаковый будет смысл.

Еще и сокращать можно. Например, так:

esp32#>if ris 5 lo 6 ex my_script

Все ключевые слова можно сокращать. Шелл разберется :slight_smile:

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

Вообще, синтаксис такой (квадратные скобки - оцпиональный параметр, звездочка - повторять то, что в квадратных скобках 0 или больше раз):

  1. Ловит прерывания:

if rising | falling PIN [low | high PIN]* [max-exec NUM] [rate-limit MSEC] exec TEXT

  1. Поллит:

if low | high PIN [low | high PIN]* [max-exec NUM] [poll MSEC] exec TEXT

есть еще третий вариант: аргумент=значение. у меня как раз третий вариант, просто я знак “=” не использую. Наверно, кому-то легче читать

if 10=rising 5=low 6=high exec ...

Этого недостаточно.
Надеюсь, сэр в курсе что
if 10=rising & 5=low & 6=high
и
if 10=rising | 5=low | 6=high
имеют немножко разный смысл?

Афоризм в тему:
Внося свою лепту, не выноси чужую.

Вывод: не стоит пытаться придумать какую-то свою собственную алгебру логики, гораздо разумнее воспользоваться тем, что было создано до тебя. Минимум, по трем основаниям:

  1. Это проще с точки зрения разработки.
  2. Меньше вероятности наделать ошибки, в том числе такие, для исправления которых придется переписывать все с нуля.
  3. Это существенно упрощает жизнь тем, кто решит воспользоваться плодами твоей деятельности: они будут освобождены от изучения нового (лишнего?) языка программирования.
2 лайка

Ты не поверишь, но ^, * и & тоже имеют разный смысл.
Причем тут твои или-палки?

У меня тольки И условия. ИЛИ условия делаются путем создания нескольких правил.

Например:

if rising 10 low 6  exec Command
if rising 10 low 5  exec Command

Что в переводе на русский как раз то, что ты хочешь:

if rising 10 AND (low 6 OR low 5) exec Command

Я и не придумывал. Это еще в начале девяностых придумали и реализовали в Cisco IOS (см. access-list). Условия по И собираются горизонтально, по ИЛИ - вертикально.

То же самое в ipfilters в Linux. Странно, что тебя такая обычная вещь возбудила. Все там есть. И И и ИЛИ. Полный базис.

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

так логику в ней русские писали )))
PS Ардуино и CISCO IOS понятия несовместимые !?

Я , если честно, не понял претензии. Язык какой-то учить, какие-то “или” условия.

ИЛИ не корячится в строчку без скобок. Вернее, вместе с И. Либо скобки, либо ортогонально разносить, что я и сделал. “И” - в строчке, “ИЛИ” - в наборе, собственно, правил.

А скобки - это уже излишество нехорошее, внатуре язык.

Условия можно писать одинаковые - они все сработают:

Кому лень учить новый язык - те жмут знак вопросика:

Это, конечно, хорошо, но хотелось бы еще, чтобы было удобно. Функции Шеффера или Пирса каждая сама по себе является полным базисом, но применение их сильно ограничено рядом конкретных частных случаев. И исключительно потому, что ими не очень удобно пользоваться.

Как ты себе видишь синтаксис? Выполнять нужно действия по событиям на пинах.

Если есть соображения, как улучшить - прошу поделиться :slight_smile: