Лучшая стратегия для анализа 5-байтовых массивов, чтобы найти шаблон
Хорошо, вот и все, мой первый вопрос, опубликованный на stackexchange! Пожалуйста, будьте нежны со мной!
Я использую Arduino UNO (на данный момент я перейду на более быстрый микропроцессор позже, но по-прежнему использую скетч Arduino) для считывания данных в качестве ведомого SPI для извлечения данных дисплея из коммерческого продукта, который не имеет другой пригодный для эксплуатации вывод данных, который я могу использовать. Я использую очень общий скетч, опубликованный Ником Гэммоном с целью демонстрации возможностей, и я могу прочитать поступающие данные SPI. (Спасибо, Ник!)
Данные берутся из коммерческого продукта с 8-символьным матричным светодиодным дисплеем 5X7, который был специально создан для этого продукта. продукты, которые я смог использовать, чтобы немного понять, как работает часть, я просто исходил из предположения, что даже если интерфейсы не одинаковы, они, вероятно, не заново изобретали свою структуру команд. Однако; в дисплей не встроен хороший чип драйвера, как в типичный параллельный ЖК-дисплей.
Чтобы выяснить это, мне пришлось провести обратный инжиниринг с помощью логического анализатора:
- Это данные SPI на частоте 4 МГц.
- Суть входящих команд и их порядок
- Используется Excel для преобразования отображения пикселей дисплея в шрифт, фактически отображаемый на устройстве.
- Что отображаемый шрифт/текст для каждого из 8 символов состоит из 5 байтов, где битовые позиции этих байтов в конечном итоге зажигают крошечный светодиод на дисплее, поэтому буква «H» выглядит как 0x7F, 0x08, 0x08, 0x08, 0x7F. Каждый байт управляет столбцом из 7 светодиодов, игнорируя строку.
Прямо сейчас:
- Я использую модифицированную версию скетча подчиненного устройства Ника, чтобы просто извлечь первые 44 байта командной строки для отображения чего-либо на дисплее
- для меня важны только 40 байт после первых 4
- потому что отображаются именно эти байты. Я беру 5 элементов 44-байтового массива, которые, как я знаю, соответствуют символу, и выплевываю их на последовательный монитор, например:
0x00, 0x01, 0x5F, 0x11, 0x00 // i 0x7F, 0x08, 0x08, 0x08, 0x7F // H etc...
А теперь, после длинного вступления, собственно вопрос:
Мне нужно проанализировать шаблоны каждого из 5 байтов, составляющих букву, и преобразовать их в текст ASCII, чтобы фактическое слово отображалось на последовательном мониторе.
Когда я использовал другой язык/среду программирования для PIC, у нас были такие вещи, как ПРОСМОТР и ПРОСМОТР, которые делали сравнение шаблонов немного более абстрактным, что странно, учитывая Arduino...
Мне нужна помощь в разработке функции, которая берет 5 байтов, необходимых для построения каждой буквы, и, возможно, сравнивает их с массивом, представляющим каждую возможную букву, а затем, возможно, передает соответствующий результат другой функции для построения/объединения. отображаемое слово из этих символов? Этот метод звучит дико неэффективно, но это все, что может придумать мой маленький мозг, и я не знаю, как это сделать... Мне не нужно много проверять ошибки, потому что до сих пор данные, которые я получение точно совпадает с тем, что я вижу на реальном дисплее - мы также говорим одно слово из 8 символов (максимум) за раз, и это довольно статично, без прокрутки слов или много болтовни - просто одно слово или некоторые данные, которые меняется относительно редко. Но отображаемые данные могут отличаться от последних настолько, что о попытках сопоставить целые слова не может быть и речи, если только это не дополнительная функция для ускорения процесса. Я думаю, что работать должным образом, это должно работать на одном символе из 8 - по одному. Другая мысль, возможно, состоит в том, чтобы суммировать 5 байтов, чтобы определить, есть ли у нас совпадение или нет, но я не уверен, что два разных символа могут иметь одинаковую сумму? Математика не моя сильная сторона. Спасибо за любую помощь.
@Ryan, 👍0
Обсуждение1 ответ
Лучший ответ:
На самом деле это проблема чисто программирования, а не Arduino, но для начала вы можете выполнить поиск в таблице, например так:
#include <stdio.h>
#include <string.h>
// количество элементов в массиве
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
unsigned char patterns [] [5] =
{
{ 0x7F, 0x08, 0x08, 0x08, 0x7F }, // Н
// другие шаблоны байтов здесь
}; // конец шаблонов
char patterns_converted [] =
{
'H',
// другие эквиваленты букв здесь
}; // конец pattern_converted
char convert_pattern (unsigned char what [5])
{
for (int i = 0; i < ARRAY_SIZE (patterns_converted); i++)
if (memcmp (what, patterns [i], 5) == 0)
return patterns_converted [i];
return '?';
} // конец convert_pattern
int main ()
{
unsigned char test1 [5] = { 0x7F, 0x08, 0x08, 0x08, 0x7F };
unsigned char test2 [5] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE }; // не будет найдено
char x = convert_pattern (test1);
printf ("Result for test1 is %c\n", x);
x = convert_pattern (test2);
printf ("Result for test2 is %c\n", x);
}
Вы бы узнали все свои битовые шаблоны и поместили их в массив шаблонов, а затем поместили эквивалентную букву в массив pattern_converted.
Функция convert_pattern выполняет линейный поиск в таблице шаблонов, возвращая соответствующую букву или "?" если не найдено.
Я закодировал его на чистом C++, но, поскольку среда разработки Arduino в основном использует C++, вы сможете преобразовать его для собственного использования.
Спасибо Спасибо! Ник Гэммон снова спасает положение! Я смог преобразовать ваш чистый C++ в Arduino-C++ и построить свою таблицу поиска и тестовые примеры, и это прекрасно работает! Теперь мне просто нужно добавить небольшой код для сравнения последних отображаемых данных с новыми, чтобы они не обновлялись без необходимости. Извините за все слова - у меня проблемы с краткостью., @Ryan
- Как использовать SPI на Arduino?
- Работает ли конструкция int array[100] = {0} на Arduino?
- Массив динамического размера в качестве члена класса
- Итерация массива объектов
- Как получить размер (sizeof) массива структур
- Работает с gcc, но не с Arduino. ошибка: taking address of temporary array
- Безопасно ли использовать std::array (из C++ STL) на Arduino? Использует ли он динамическое выделение памяти?
- Arduino UNO + Ethernet Shield + ЖК-дисплей + RFID, но RFID не работает
не вижу причин для такого длинного поста... похоже, вы хотите декодировать данные, идущие на точечный матричный дисплей 5x7, и определить, какой символ отображается... данные поступают по SPI.... я так понимаю это правильно?, @jsotola
Сколько различных символов может быть отображено? 10? Разве вы не можете просто использовать таблицу поиска?, @Nick Gammon
Таким образом, это светодиод 5x7 (то есть 35 различных светодиодов на символ), и, таким образом, 5 символов (по 8 бит каждый) позволяют использовать 40 комбинаций, поэтому 5 не используются. Это правильно до сих пор? Таблица поиска всех фактических поступающих символов, вероятно, самая простая, вы можете сохранить ее в PROGMEM., @Nick Gammon
Сравнение всех байтов для каждого символа может показаться неэффективным, но MCU работает довольно быстро. Поэтому, если у вас нет чего-то другого, требующего большого количества вычислений, этого будет достаточно быстро. Хотя вы действительно можете попробовать сделать некоторые трюки, например добавить байты (как вы предложили) или XOR пяти байтов. Мне нравится использовать Excel для этих целей. Поместите 5 байтов в пять столбцов. Поместите формулу в последний столбец. Затем проверьте, являются ли все рассчитанные значения [уникальными] (https://www.exceltrick.com/how_to/count-unique-values-excel/?). Вы также можете попробовать использовать только определенные столбцы пикселей., @Gerben
Если вы опубликуете пиксельные данные для всех персонажей, я готов сделать это за вас, так как это звучит как забавное упражнение. Хотя, как я уже сказал, это, вероятно, не нужно., @Gerben
Если у вас есть большой набор данных, вы можете реализовать поиск по дереву. Вершина дерева — это все возможные первые байты. Следующий слой — это возможные вторые байты, следующие за каждым возможным первым байтом — и т. д. Или вы можете создать частичное дерево — где у вас есть ряд массивов байтов 2-5 (которые на самом деле могут быть 32-битными целыми числами) и эти массивы группируются по первому байту. Если у вас все в порядке, вы также можете «разделять и властвовать» в своем наборе данных вместо линейного поиска. Существует множество алгоритмов на выбор., @Majenko
Еще одна мысль: массив пикселей 5x7 дает вам 35 бит данных. Если вы можете найти 3 пикселя, которые *никогда* не включаются, вы можете отбросить их и сжать данные до 32 бит. Это может быть легко представлено в виде числа, которое Arduino может обработать и упростить поиск. Особенно, если вы должны были использовать разделяй и властвуй, чтобы сузить данные, поскольку > и < проще с чистым числом., @Majenko
XOR был бы плохим выбором для создания «контрольной суммы». Симметричные буквы (которых много) сведут на нет большую часть операции XOR, оставив вам только значение среднего байта., @Majenko