Irinka
14.Август.2024 19:51:08
1
Здравствуйте.
Имею 20 светодиодов WS2812B.
Нужно покадрово их включать.
Пример
Можно создать многомерный массив и хранить в нем 1 и 0 (20 светодиодов, 6 кадров, 120 байт, можно занести в PROGMEM, но я так не хочу).
Переменная типа uint32_t весит 4 байта, то есть 32 бита.
120/32 = 3,75 переменных типа uint32_t , то есть 4 переменных uint32_t .
В Excel я соединила все строки в одну и разделила их по 32 бита, соответственно получила 4 переменных.
const uint32_t cadr[5] = {
0b11000000000000001001100000000001,
0b00000011000000000000000001100000,
0b00000000000011000000000000000000,
0b00000000000000000000000000000001,
0b00000000000000000000000000000001
};
Теперь на каждый кадр мне нужно получить по 20 значений 0 и 1.
То есть:
1 кадр - это 0 элемент массива, биты с 0 по 19 (20 бит)
2 кадр - это 0 элемент массива, биты с 20 по 32 (12 бит) и 1 элемент массива, биты с 0 по 19 (оставшиеся 20 бит)
и так далее
Вот примерно так получилось объяснить.
Как мне это реализовать?
Возьмите просто на каждый кадр по uint32_t.
Потом просто первые (или последние) 20 бит перебираете в цикле и соответственно в массиве фастледа, к примеру, выставляете черный или карминный цвет.
А с вашим компактным способом только пальцы изобъете об клавиатуру. 6 кадров того не стоят.
А так… Можете функцию написать, можете класс, который делает что-то типа:
uint8_t ledNo = …;
arrayIdx = ledNo / 32;
bitIdx = ledNo - (arrayIdx * 32);
Irinka:
Как мне это реализовать?
Можно так попробовать
Установка бита в 1 в массиве
uint32_t mass[4] = {0, 0, 0, 0};
void write1_mass(uint32_t *massiv, uint16_t index, byte bitNumber)
{
*(massiv + index) |= (1UL << bitNumber);
}
Запись в бит нуля , и чтение - аналогично
P.S. Пример. Устанавливаем по очереди биты начиная с 0 элемента массива
Спойлер
uint32_t mass[4] = {0, 0, 0, 0};
void write1_mass(uint32_t *massiv, uint16_t index, byte bitNumber)
{
*(massiv + index) |= (1UL << bitNumber);
}
void setup() {
Serial.begin(9600);
}
void loop() {
static uint16_t ind = 0;
static byte bitN = 0;
write1_mass(mass, ind, bitN);
for(byte ii = 0; ii < 4; ii++)
{
Serial.print(mass[ii], BIN);
Serial.print(' ');
}
Serial.println();
bitN++;
if(bitN > 19)
{
bitN = 0;
ind++;
}
if(ind > 3)
for(;;);
}
Спойлер
Еще вариант - двумерный массив Anima[kadr][3] на каждый кадр 3 байта. Номер байта в кадре находится по формуле (Nled / 8) номер бита (Nled % 8) далее битовые операции.
@ЕвгенийП как то выкладывал софт для оперирования битами в любом количестве.
Irinka
15.Август.2024 04:33:56
6
Кадров будет много.
*(massiv + index) |= (1UL << bitNumber);
Что значит 1UL ?
BOOM
15.Август.2024 04:47:22
8
Irinka:
Что значит 1UL ?
1 U nsigned L ong
Это чтобы компилятор приведение типа не сделал.
lilik
15.Август.2024 04:48:57
9
Есть же нормальные, текстовые функции:
bitRead() и bitWrite()
https://www.joyta.ru/10813-arduino-funkcii-bity-i-bajty/
… а не эти богомерзкие >> и << . Кстати они означают на самом деле “много больше” и “много меньше” Т.е. 1000>>1 и 1<<1000.
BOOM
15.Август.2024 04:49:41
10
Это только в математике, а не в программировании.
BOOM
15.Август.2024 04:50:46
11
Кстати, в этом примере, на мой взгляд это лишнее…
Irinka:
Найти бы)
Навеяно https://forum.arduino.cc/index.php?topic=156141.0 (осадочек остался, как до меня дошёл слушок что bool=byte, если речь об адресации). Этюды читать не доставляет (там срач с Архатом и выяснение перспективности/ущербности использования ООП), а...
а вот здесь с доработкой на случай, если нужен доступ к отдельным битам по именам
Там, кстати, за это время протухла ссылка на Printing
, сейчас она вот здесь живёт .
1 лайк
Что-то я не совсем понимаю - как красиво заинитить этот булев массив сразу при создании?
С простым всё понятно uintXX_t arr[3] = { 1, 0 , 1 } , а тут как?
Добавить конструктор с тем параметрами, какие нужны и инициализировать в конструкторе.
MMM
15.Август.2024 07:14:09
15
Если bitNumber
больше 15 - не лишнее
1 лайк
Ну да, ну да))
Arduino.h
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
в моём примере bitSet()
Хотите верьте - только сейчас глянул.
Irinka
15.Август.2024 10:18:53
17
#include "BoolArray.h"
static const int8_t totalBools = 120;
static CBoolArray<totalBools> booleanArray;
void setup() {
Serial.begin(9600);
}
void loop() {
}
Я создала переменную 120 бит.
А как мне их сразу забить 1 и 0 ?
А во Flash память можно сохранить будет?
Если непонятна подобная запись
Спойлер
uint32_t mass[4] = {0, 0, 0, 0};
void write_mass(uint32_t *massiv, uint16_t index, byte bitNumber, bool Bit)
{
bitWrite( *(massiv + index), bitNumber, Bit);//упрощаем по заветам Lilik'a
}
void setup() {
Serial.begin(9600);
}
void loop() {
static uint16_t ind = 0;
static byte bitN = 0;
bool BIT;
bitN % 2 ? BIT = true : BIT = false;//определяем чётные и нечётные биты
write_mass(mass, ind, bitN, BIT);
for(byte ii = 0; ii < 4; ii++)
{
Serial.print(mass[ii], BIN);
Serial.print(' ');
}
Serial.println();
bitN++;
if(bitN > 19)
{
bitN = 0;
ind++;
}
if(ind > 3)
for(;;);
}
Спойлер
1 лайк
Нулями они уже забиты. Для единиц нужен конструктор, я уже писал @sadman41
В том виде, как сейчас сделано - нет. Если нужно, то всё можно, конечно.