Робот-балансир
Кому интересно, ссылка на такого робота
p.s.
Сохраняйте страницу в закладки, чтобы не потерять.
Реклама: ООО "АЕР Услуги" ИНН: 7703380158
Кому интересно, ссылка на такого робота
p.s.
Сохраняйте страницу в закладки, чтобы не потерять.
Реклама: ООО "АЕР Услуги" ИНН: 7703380158
Кому интересно, ссылка на такого робота
p.s.
Сохраняйте страницу в закладки, чтобы не потерять.
Реклама: ООО "АЕР Услуги" ИНН: 7703380158
После прошлых частей, тестирование:
Подключаем STM32F429IGT6 noname boards USB<>Type-C к ПК
Что на картинке)... После запуска, необходимо перейти на вкладку View(1) -> Live Watch(2) (появится область где можно онлайн смотреть переменные, их надо добавить, то есть прописать(4)), далее View -> Memory -> Memory 1 -> в области Go to прописать 0xD0000000
После чего жмакаем) (6)
Расшифровка: 55 aa мы тестово прописали в коде данные значения теперь они физически работают для SDRAM (FSMC). Динамические переменные правые данные это уже область работы NAND флешки, Maker_id и Devoce_id вроде у всех должны быть именно такие. Статусы HAL_OK (0) говорят, что все успешно работает.
Нафига?)
Первое: поиски в "инете" особо не помогли
Второе: отличная шпаргалка
Третье: при всем этом, почти готовая платформа LTDC (ЖКИ RGB888, RGB565 и еже с ними)
Вот и всё
Послесловие: ИИ по коду лучше меня объяснит, что?как?почему?
В прошлой части остановились по сборке проекта, в этой части программный код.
И так у нас готовый проект, согласованный с CubeMX
переходим в файл main.c (данный файл сформирован под настройки первой части, это надо для согласования CubeMX и IAR)
находим область в main.c
/* USER CODE BEGIN PV */
"(здесь код пользователя)"
/* USER CODE END PV */
копируем код (ctrl-c):
NAND_IDTypeDef g_nand_id;
volatile HAL_StatusTypeDef g_erase_status = HAL_ERROR;
volatile HAL_StatusTypeDef g_read_status = HAL_ERROR;
volatile HAL_StatusTypeDef g_write_status = HAL_ERROR;
NAND_AddressTypeDef g_erase_addr;
uint8_t g_write_buf[2048];
uint8_t g_read_buf[2048];
/* Адреса областей FMC NAND Bank3 */
const uint32_t g_data_area = 0x80000000u;
const uint32_t g_cmd_area = 0x80000000u | 0x00010000u; /* 0x80010000 */
const uint32_t g_addr_area = 0x80000000u | 0x00020000u; /* 0x80020000 */
вставляем копированный код (ctrl-v) в область
/* USER CODE BEGIN PV */
>>> ctrl-v <<<
/* USER CODE END PV */
ниже в файле main.c находим
/* USER CODE BEGIN 0 */
"(здесь код пользователя)"
/* USER CODE END 0 */
копируем код (ctrl-c):
/* Ожидание готовности NAND по линии R/B# (PB13). */
static HAL_StatusTypeDef NAND_WaitReady(uint32_t timeout_ms)
{
uint32_t start = HAL_GetTick();
while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == GPIO_PIN_RESET)
{
if ((HAL_GetTick() - start) > timeout_ms)
{
return HAL_TIMEOUT;
}
}
return HAL_OK;
}
/* Чтение байта статуса NAND (команда 0x70) */
static uint8_t NAND_ReadStatusByte(void)
{
*(volatile uint8_t *)g_cmd_area = 0x70;
return *(volatile uint8_t *)g_data_area;
}
вставляем копированный код (ctrl-v) в область
/* USER CODE BEGIN 0 */
>>> ctrl-v <<<
/* USER CODE END 0 */
ниже в файле main.c находим
/* USER CODE BEGIN 2 */
"(здесь код пользователя)"
/* USER CODE END 2 */
копируем код (ctrl-c):
/* ================= SDRAM INITIALIZATION SEQUENCE ================= */
FMC_SDRAM_CommandTypeDef Command;
uint32_t tmpmrd = 0;
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
HAL_Delay(1);
Command.CommandMode = FMC_SDRAM_CMD_PALL;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command.AutoRefreshNumber = 1;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command.AutoRefreshNumber = 8;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
tmpmrd = (uint32_t)(0u << 0) | (uint32_t)(0u << 3) |
(uint32_t)(3u << 4) | (uint32_t)(1u << 9);
Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = tmpmrd;
(void)HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
(void)HAL_SDRAM_ProgramRefreshRate(&hsdram1, 1385);
HAL_Delay(10);
/* ================= SDRAM TEST ================= */
{
volatile uint16_t *sdram_ptr = (volatile uint16_t *)0xD0000000u;
*sdram_ptr = 0xAA55u;
volatile uint16_t sdram_rd = *sdram_ptr;
(void)sdram_rd;
}
/* ================= NAND: инициализация адреса ================= */
g_erase_addr.Plane = 0;
g_erase_addr.Block = 0;
g_erase_addr.Page = 0;
for (int i = 0; i < 2048; i++)
{
g_write_buf[i] = (uint8_t)(i & 0xFF);
}
/* ================= NAND TEST ================= */
HAL_NAND_Reset(&hnand1);
HAL_Delay(10);
HAL_StatusTypeDef nand_status = HAL_NAND_Read_ID(&hnand1, &g_nand_id);
if (nand_status == HAL_OK)
{
volatile uint32_t maker = g_nand_id.Maker_Id;
volatile uint32_t device = g_nand_id.Device_Id;
volatile uint32_t third = g_nand_id.Third_Id;
volatile uint32_t fourth = g_nand_id.Fourth_Id;
(void)maker; (void)device; (void)third; (void)fourth;
}
else
{
volatile uint32_t err = 1;
(void)err;
}
/* ================= NAND: стирание блока 0 ================= */
*(volatile uint8_t *)g_cmd_area = 0x60;
*(volatile uint8_t *)g_addr_area = (uint8_t)((g_erase_addr.Block >> 8) & 0xFF);
*(volatile uint8_t *)g_addr_area = (uint8_t)( g_erase_addr.Block & 0xFF);
*(volatile uint8_t *)g_cmd_area = 0xD0;
/* tWB: NAND должен успеть «дёрнуть» R/B# вниз */
for (volatile int d = 0; d < 1000; d++);
HAL_StatusTypeDef erase_wait = NAND_WaitReady(100);
if (erase_wait != HAL_OK)
{
g_erase_status = HAL_TIMEOUT;
}
else
{
uint8_t st = NAND_ReadStatusByte();
g_erase_status = ((st & 0x01u) == 0u) ? HAL_OK : HAL_ERROR;
}
/* ================= NAND: запись страницы 0 блока 0 ================= */
*(volatile uint8_t *)g_cmd_area = 0x80;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
for (int i = 0; i < 2048; i++)
{
*(volatile uint8_t *)g_data_area = g_write_buf[i];
}
*(volatile uint8_t *)g_cmd_area = 0x10;
for (volatile int d = 0; d < 1000; d++);
HAL_StatusTypeDef prog_wait = NAND_WaitReady(50);
if (prog_wait != HAL_OK)
{
g_write_status = HAL_TIMEOUT;
}
else
{
uint8_t st = NAND_ReadStatusByte();
g_write_status = ((st & 0x01u) == 0u) ? HAL_OK : HAL_ERROR;
}
/* ================= NAND: чтение страницы 0 блока 0 ================= */
*(volatile uint8_t *)g_cmd_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_addr_area = 0x00;
*(volatile uint8_t *)g_cmd_area = 0x30;
/* tWB: критически важно, иначе NAND не успеет перевести R/B# в низкий уровень */
for (volatile int d = 0; d < 5000; d++);
/* tR: по даташиту W29N01HV максимум 25 мкс, 1 мс с большим запасом */
HAL_Delay(1);
/* Чтение данных: никакой команды 0x70 здесь быть не должно */
for (int i = 0; i < 2048; i++)
{
g_read_buf[i] = *(volatile uint8_t *)g_data_area;
}
/* Сравнение: только по содержимому, без статусного байта */
uint32_t mismatch = 0;
for (int i = 0; i < 2048; i++)
{
if (g_read_buf[i] != g_write_buf[i])
{
mismatch++;
}
}
g_read_status = (mismatch == 0) ? HAL_OK : HAL_ERROR;
вставляем копированный код (ctrl-v) в область
/* USER CODE BEGIN 2 */
>>> ctrl-v <<<
/* USER CODE END 2 */
Далее собираем проект
В следующей части, запуск и тестирование, что в итоге получилось.
Задача: запустить по минималке.
Дано: stm32f429igt6 noname board, на борту есть SDRAM память W9825G6KH-6 = 256 Мбит, NAND Flash W29N01HVSINA = 1 Гбит, программатор ST-LINK/V2 (disco), схемы наверное есть (лично я не нашел и особо не искал)
Покупал в маркетплейсе, не дорого.
ПО для работы:
Stm32 CubeMX (6.10.0 и выше)
локальная библиотека под камни F4 (CubeMX)
IAR (9.30.1)
Измерительные приборы:
Мультиметр
Шнур USB<>Type-C
Начнём:
Запускаем CubeMX
File->New Project ... (Ctrl+n) (Создание нового проекта)
Почему именно локальные библиотеки?!, ответ: доступ закрыт...
Если всё получилось правильно, после генерации кода, находим собственную папку с проектом, запускаем проект IAR, находим main.c
собираем проект, должно получится без ошибок, далее обязательные шаги надстройки IAR
вот тут надстройка не обязательна, просто бывает глючит JTAG,поменял на SWD
конец первой части.
Кому интересно, ссылка на такого робота
p.s.
Сохраняйте страницу в закладки, чтобы не потерять.
Реклама: ООО "АЕР Услуги" ИНН: 7703380158
ChemBus Controller (контроллер химической шины pH/EC)
Перед каждым, кто работает с жидкостными контурами — от домашнего энтузиаста на гидропонике или аэропонике до полупромышленного хозяйства — рано или поздно встаёт один и тот же вопрос: что на самом деле в растворе. Питательные вещества, pH, EC, загрязнения — всё это нужно видеть, и видеть точно. ChemBus Controller решает одну из этих задач: индуктивное измерение EC и кислотности pH с развязкой по питанию, отдельными АЦП на канал и шаговым дозированием.
Применим он шире: водное хозяйство (пруды, бассейны, оборотные воды), аквакультура, контроль загрязнения жидкости — везде, где нужно следить за электропроводностью и кислотностью.
Проект спроектирован так, чтобы работать на простом ESP32 или на модуле ESP32-S3 Waveshare 1.47". На борту — STM32F407VET6, RS485 и гальваническая развязка по питанию для каналов pH и EC.
Измерение — EC индуктивное, по каждому каналу свой АЦП:
MCP3551 — под EC,
ADS1232 — под pH.
Для температурной компенсации предусмотрен датчик DS18B20, а внешний климат снимает DHT22 (температура и влажность).
Канал I2C подвязан к ESP32. Под дозирование — два модуля шаговых двигателей A4988: pH UP и pH DOWN.
По статусу: проект двигается по возможности. Прототип был в прошлых постах, есть и промежуточная версия. В GitHub пока много ошибок, до порядка руки не доходят — времени не хватает.
Код и схема: https://github.com/Rikidevice/EC_inductors
Библиотека написана с нуля на чистом языке C в GCC и AC6 используя только целочисленную математику и не используя сторонние коды.
На данный момент библиотекой поддерживается два микроконтроллера ATmega128 и STM32F407 на уровне графического интерфейса пользователя GUI (KVB_LCD.h). Графические объекты, написанные на основе GUI библиотеки, будут работать как на 8 ми битном микроконтроллере ATmega128 так и на 32 х битном STM32F407.
Для разработки программного кода библиотекой поддерживаются три среды разработки IDE; Atmel Studio 7.0, STM32CubeIDE v2 и Keil MDK v5.43. Для просмотра тестового презентационного кода под STM32 поддерживаются три платы разработки с разъемом FSMC;
Open407V-D stm32f4-discovery микроконтроллер STM32F407VGT6.
ST STM32F4XX Black v3.0 1606 микроконтроллер STM32F407ZGT6.
ST STM32F4XX Black v2.0 1509 микроконтроллер STM32F407VET6.
Для просмотра тестового презентационного кода под ATmega128 используются порты ввода / вывода;
PORTC порт (D0-D7) младшего байт шины данных LCD панели.
PORTA порт (D8-D15) старшего байт шины данных LCD панели.
PORTD бит 4 (CS) передача сигнала доступа к LCD панели.
PORTD бит 5 (RD) передача сигнала чтения из LCD панели.
PORTD бит 6 (WR) передача сигнала записи в LCD панель.
PORTD бит 7 (RS) передача сигнала команда/данные LCD панели.
PORTG бит 0 (RST) передача сигнала сброса LCD панели.
PORTG бит 1 (BL) передача сигнала подсветки LCD панели.
На данный момент написаны драйвера для пяти LCD панелей:
ILI9325 разрешение 320 x 240
ILI9341 разрешение 320 x 240
ILI9481 разрешение 480 x 320
ILI9484 разрешение 480 x 320
OTM8009A разрешение 800 x 480
Расположение выводов разъемов плат и панелей прилагаются в папке “FSMC LCD” в виде документов в формате .xlsx. Вполне возможно, что у Вас могут отличатся разъемы LCD панелей, но разъемы плат должны соответствовать.
Основной задачей при создании библиотеки ставилось, кроме кроссплатформенности, максимально быстрая отрисовка графических объектов. В отличие от классических библиотек, использующих стандартный по пиксельный вывод, в данном проекте реализованы собственные оптимизированные алгоритмы, разработанные с учетом архитектуры графической памяти (GRAM) дисплеев:
Скоростная отрисовка линий. Используется авторский алгоритм, который рассчитывает сплошные прямые отрезки в наклонных линиях. Это позволяет минимизировать количество команд переключения адресов GRAM LCD панели и осуществлять быструю блочную заливку, что кратно увеличивает скорость отрисовки (FPS).
Отрисовка градиентным цветом. Используется авторский алгоритм, который рассчитывает и заполняет градиентное окрашивание в вертикальном и горизонтальном направлении с линейной или центральной ориентацией за счет аппаратного ускорения GRAM матрицей LCD панели.
Многофункциональный трех поверхностный объект. Используется авторский алгоритм, который рассчитывает в целочисленной математике окружность с заполнением градиентным цветом на лету не используя фрейм-буферы. В данном объекте заполняются и отрисовываются одновременно три округлые / круглые или прямоугольные поверхности градиентным цветом в разных направлениях на лету. Все три поверхности могут перерисовываться независимо друг от друга, это позволяет, акцентировать выбор объекта, перерисовывая другим цветом только одну, на пример, наружную поверхность не тратя время на отрисовку остальных поверхностей.
Движок обладает мощным и быстрым функционалом работы с текстом, который автоматически выравнивает строки и рендерит сложные визуальные эффекты на лету без использования фрейм-буфера:
Привязка к базовой линии. Все шрифты привязываются к единой горизонтальной направляющей, нижняя полка символов. Это позволяет собирать одну строку из слов разного размера и цвета, гарантируя идеальную ровность текста.
Автоматический перенос длинного текста по словам. Длинный непрерывный текст может состоять из множества текстовых, целочисленных и вещественных переменных, разного размера шрифта окрашенных разным цветом. Текст будет переносится по словам на следующие строки если выходит за границу ширины текстового блока.
Поддержка табуляции.
Установка кернинга шрифта (меж символьное расстояние) с коррекцией длины пробелов и табуляции.
Расстояния между строками. Расстояние задается как в плюс, так и в минус. Актуально в минус если длинный текст выводится только заглавными символами. Изменение расстояния в плюс приводит к лучшей читаемости обычного текста.
Коэффициент увеличения шрифта.
Выравнивание текста. Выравнивание задается по левому краю, правому краю или центру.
Эффект тени. Тень символа имеет четыре установки. 1 = тень низ справа, 2 = тень низ слева, 3 = тень верх справа, 4 = тень верх слева. Тем самым создается эффект выпуклости или вдавленности шрифта и лучшем образом влияет на читаемость текста.
Круговой контур символов. Четкий контур вокруг каждого символа для читаемости на любом фоне. Можно задать отображение только контура без символа.
Градиентный текст. Плавное окрашивание в горизонтальном или вертикальном направлении с помощью линейной или центральной заливки строки и применению тени или кругового контура.
Для создания и кастомизации экранных шрифтов разработано полноценное Windows-приложение, автоматизирующее весь цикл подготовки графических ресурсов:
Импорт DOS-шрифтов (.fnt). На протяжении DOS эпохи было создано великое множество растровых шрифтов .fnt формата. Возможность быстрой загрузки классических растровых шрифтов формата DOS для их последующей адаптации под дисплеи микроконтроллеров.
Поточечное редактирование. Удобный графический интерфейс для ручной отрисовки и корректировки каждого символа на пиксельной сетке с настройкой базовой линии.
Интерактивный рендеринг. Отображение заданной текстовой строки на лету в реальном времени. Вы видите, как изменения конкретного пикселя в символе влияют на отображение целой строки.
Сохранение в Си-формат. Генерация готовых `.c` файлов с ультра-компактной последовательной упаковкой данных (символ 9x16 занимает всего 18 байт), полностью совместимых как с `PROGMEM` во Flash-памяти ATmega128, так и с обычными константными массивами в STM32F407.
Авторский пак. С помощью данного редактора создано 23 уникальных русско-английских шрифта (5 базовых включены в презентацию для демонстрации, полный набор и редактор доступны по запросу).
В демонстрационной версии редактора убрана возможность сохранения в Си-формате, полноценный редактор доступен по запросу.
Видео ролик можно посмотреть, оценить скорость работы:
Полный код проекта и описания можно скачать: