• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Делюсь опытом AdHoc пошаговое руководство

pvvx

Активный участник сообщества
куда как интереснее послушать как в Power Profiler сделано сейчас.
Код:
typedef struct {
    uint8_t dev_addr; // адрес на шине i2c
    uint8_t reg_addr; // номер регистра чтения
} reg_rd_t;

typedef struct {
    uint8_t dev_addr; // адрес на шине i2c
    uint8_t reg_addr; // номер регистра чтения
    uint16_t data; // значение для записи в регистр
} reg_wr_t;

#define MAX_INIT_REGS 4
#define MAX_READ_REGS 4

// Структура конфигурации опроса и инициализации устройства
// Выходной пакет непрерывного опроса формируется по данному описанию
typedef struct {
    uint8_t rd_count; // кол-во регистров для разового чтения
    uint8_t init_count; // кол-во регистров для инициализации
    uint16_t time; // частота опроса разового чтения
    uint16_t clk_khz; // частота i2c шины
    reg_wr_t init[MAX_INIT_REGS];
    reg_rd_t rd[MAX_READ_REGS];
} dev_cfg_t;

// Выходной пакет примерно такой
typedef struct {
    uint8_t id; // тип пакета   
    uint8_t cnt; // последовательный номер пакета
    uint16_t reg[кол-во]; // сборка регистров указанная в кол-ве регистров для разового чтения и описание какие в reg_rd_t,
    // набор до 30 шт при USB-UART USB1.1 (до 64 байта пакет),
    // кол-во зависит от скорости опроса ADC.
} out_pkt_t;
 

cheblin

Member
C:
typedef struct {
    blk_head_t head;
    union {
        uint8_t  uc[VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)];
        int8_t   sc[VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)];
        uint16_t ui[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(uint16_t)];
        int16_t  si[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(int16_t)];
        uint32_t ud[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(uint32_t)];
        int32_t  sd[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(uint32_t)];
        reg_wr_t reg;
    }          data;
} blk_cio_t;
и вот это... спасибо.
 

pvvx

Активный участник сообщества
Более конкретно - не задействованная возможность на верхнем уровне ПО по дерганию ножками данного MCU.
В другом ПО это выглядит так:
upload_2020-1-10_20-34-55.png
И каждый кружок вызывает конфигурацию вывода:
upload_2020-1-10_20-35-36.png
Более детально что это всё значит смотреть в PDF на использованный MCU.
 

pvvx

Активный участник сообщества
C:
typedef struct {
    blk_head_t head;
    union {
        uint8_t  uc[VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)];
        int8_t   sc[VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)];
        uint16_t ui[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(uint16_t)];
        int16_t  si[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(int16_t)];
        uint32_t ud[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(uint32_t)];
        int32_t  sd[(VIRTUAL_COM_PORT_DATA_SIZE - sizeof(blk_head_t)) / sizeof(uint32_t)];
        reg_wr_t reg;
    }          data;
} blk_cio_t;
и вот это... спасибо.
Это как выглядят разные типы данных в памяти у данного MCU и сколько их может вмещаться в пакет с ограничением в VIRTUAL_COM_PORT_DATA_SIZE, а так-же как обратиться CPU к энному элементу при одинаковом их типе в наборе :p
 

pvvx

Активный участник сообщества
Что ещё вас там интересует?

Что нужно выкинуть, т.е. сколько там ненужного и не оптимизированного кода?

Например заголовок там не удален с того века, когда писался какой-то паскалевский драйвер – он же и прикручен в основной программе. Актуальность у нем была когда вышел Borland Delphi7. С тех времен не менялся и на его основе за полчаса была сформирована первая версия PowerProfiler-а…
Что-то ещё там такое-же сидит... Но мне лень разгребать тысячный вариант своей лепнины... :)
 

pvvx

Активный участник сообщества
Вспомнил! Там по началу был дугой код USB-COM от ST, другая либа, какая-то из первых, глючная.
Потом система драйвера у ST сменилась, вместе с алгоритмами и вызовами. Но мне было лень всё переписывать. Поменял дрова, а алгоритм как-то скривил, чтобы он пахал и на новом драйвере :rolleyes:
 

cheblin

Member
понятно. тут играем, тут не играем, а тут рыбу заворачивали...

похоже переделывать придётся всё. поначалу была иллюзия встроится и клиента не ломать. но там ценнного нуль.

итак:
считываются показания uint16_t с датчиков на smbus по таймеру... так?
период отсчётов 100 us?
сколько делать отчётов в одной отправке?
подстраиваться под VIRTUAL_COM_PORT_DATA_SIZE ?

короче нужен требуемый алгоритм обмена. интересует именно главный функционал - сбора и отправки данных.
управление устройством, подстройки, и конфигурирование это всё второстепенное и делается элементарно.

Код:
// Выходной пакет примерно такой
typedef struct {
    uint8_t id; // тип пакета
    uint8_t cnt; // последовательный номер пакета
    uint16_t reg[кол-во]; // сборка регистров указанная в кол-ве регистров для разового чтения и описание какие в reg_rd_t,
    // набор до 30 шт при USB-UART USB1.1 (до 64 байта пакет),
    // кол-во зависит от скорости опроса ADC.
} out_pkt_t;
uint8_t cnt; // последовательный номер пакета
нафига?
разве USB транспорт не гарантирует очерёдность пакетов?

uint16_t reg[кол-во]; // сборка регистров указанная в кол-ве регистров для разового чтения и описание какие в reg_rd_t,
для чего это передавать?
разве устройство и клиент при коннекте не согласовывают эти настройки?




есть какие либо идеи про клиента? есть предпочтения?
 

cheblin

Member
Код:
// Выходной пакет примерно такой
typedef struct {
    uint8_t id; // тип пакета
    uint8_t cnt; // последовательный номер пакета
    uint16_t reg[кол-во]; // сборка регистров указанная в кол-ве регистров для разового чтения и описание какие в reg_rd_t,
    // набор до 30 шт при USB-UART USB1.1 (до 64 байта пакет),
    // кол-во зависит от скорости опроса ADC.
} out_pkt_t;
в исходниках out_pkt_t нет
аналог?
 

pvvx

Активный участник сообщества
в исходниках out_pkt_t нет
аналог?
Вам упрощенный пример тут в теме описал. В нем и есть out_pkt_t.
понятно. тут играем, тут не играем, а тут рыбу заворачивали...
похоже переделывать придётся всё. поначалу была иллюзия встроится и клиента не ломать. но там ценнного нуль.
А исходники PowerProfiler уже утречком пробежался, т.е. сменились - выкинуто лишнее (старые заголовки у пакета) :p
сколько делать отчётов в одной отправке?
подстраиваться под VIRTUAL_COM_PORT_DATA_SIZE ?
Задаваемая длина пакета при соединение (перед стартом передачи данных).
uint8_t cnt; // последовательный номер пакета
нафига?
разве USB транспорт не гарантирует очерёдность пакетов?
А пропуск по чьей-либо вине, включая hub?
Будем вводить сообщения об ошибках с обоих сторон?
Кароче можно без этого резервного байта...
uint16_t reg[кол-во]; // сборка регистров указанная в кол-ве регистров для разового чтения и описание какие в reg_rd_t,
для чего это передавать?
разве устройство и клиент при коннекте не согласовывают эти настройки?
Вот это и есть массив переменным размером "кол-во" в котором и лежат значения регистров с ранее оговоренной последовательностью.
 

pvvx

Активный участник сообщества
Какие у вас сложности с передачей 16 бит от устройства на i2c с задаваемым интервалом c помощью самого дешевого STM32 в USB-COM и прием в компе?
Задача на десять-пятнадцать минут с полным описанием с нуля всех исходников.

Зачем вы полезли в программу, где всё задается, до нескольких опрашиваемых устройств на i2c и с них передаются назначенные для чтения то таймеру регистры?
Да ещё и с описанием - что это выпрошенная помойка т.к. просят, мой батник, который я каждый раз что-то вписываю для конкретных нужд не глядя что там будет с другими функциями.
 

cheblin

Member
Задача на десять-пятнадцать минут
на данном подсайте гений только один - ВЫ
правда вот глядя на исходники не нахожу этому подтверждения...но ВЫне огорчайтесь ...

..а нам тупить и заниматься своими делами позволительно, да...
мы в гении не лезем.
 

pvvx

Активный участник сообщества
на данном подсайте гений только один - ВЫ
правда вот глядя на исходники не нахожу этому подтверждения...но ВЫне огорчайтесь ...

..а нам тупить и заниматься своими делами позволительно, да...
мы в гении не лезем.
У вас что комп так тормозит в STM32CubeMX? Там, в зависимости от чипа, надо вписать - в подготовленной для вас средой процедуре таймера чтение регистра i2c и значение положить в буфер. При накоплении n значений вызвать передачу буфера в USB.
Это долго?
 

cheblin

Member
upload_2020-1-11_17-26-42.png

как жеж мне "дорог" этот С... с этими постоянными клэшами имён. тьху гадость...
 

pvvx

Активный участник сообщества
Посмотреть вложение 8571

как жеж мне "дорог" этот С... с этими постоянными клэшами имён. тьху гадость...
Я вот тут подумал и осознал, свою ошибку! Каюсь. Совсем забыл, что вы с MCU никогда не работали и для вас это неопознанный мир...
Нашел SoC, который я ещё не изучал и засек время.
Ушло 22 минуты на всё - с поиском платки, проводков и прочими подготовками, да ещё общением с детками и женой....
Но больше всего после этого ушло на фото и прочую подготовку картинок для вас
"Как считать регистр значения тока из IN226 и передать в USB".
Взял nRF528240.
Открыл пару примеров и сделал копипаст мышкой. Добавил пару переменных, потоптав клаву:
Код:
/*********************************************************************
  This is an example for our nRF52 based Bluefruit LE modules
  Pick one up today in the adafruit shop!
*********************************************************************/
#include <Arduino.h>
#include <Wire.h>
SoftwareTimer blinkTimer;
void setup()
{
  Serial.begin(115200);
  while ( !Serial ) delay(10);   // for nrf52840 with native usb-com
  // Configure the timer with 1000 ms interval, with our callback
  blinkTimer.begin(50, blink_timer_callback);
}
size_t adc_buffer_wr_idx = 2;
// sends regs 0x00 config data:
// 0x0125 : 1.1 ms Shunt Only
// 0x0127 : 1.1 ms Shunt & Bus
uint8_t ina226_config[3] = {0x00, 0x01, 0x25};
uint8_t inited = 0;
uint8_t adc_buffer[62];
void loop()
{
  if (!inited) {
    adc_buffer[0] = 0x55; // header code
    adc_buffer[1] = 0x07; // block id
    Wire.begin();        // join i2c bus (address optional for master)
    Wire.setClock(TWIM_FREQUENCY_FREQUENCY_K400);
    // device address is specified in datasheet
    Wire.beginTransmission(0x40); // transmit to device 0x40
    Wire.write(ina226_config, 3); // set regs config
    Wire.endTransmission();     // stop transmitting
    inited = 1;
    // Start the timer
    blinkTimer.start();
  }
}
void blink_timer_callback(TimerHandle_t xTimerID)
{
  (void) xTimerID;   // freeRTOS timer ID, ignored if not used
  digitalToggle(LED_RED);
  // request 2 bytes from slave device 0x40 register 0x01
  if (inited) {
    Wire.beginTransmission(0x40); // transmit to device 0x40
    Wire.write(0x01);
    Wire.endTransmission();     // stop transmitting
    Wire.requestFrom(0x40, 2);
    if (2 <= Wire.available()) {   // if two bytes were received
      adc_buffer[adc_buffer_wr_idx++] = Wire.read();  // receive high byte (overwrites previous reading)
      adc_buffer[adc_buffer_wr_idx++] = Wire.read(); // receive low byte as lower 8 bits
      if (adc_buffer_wr_idx >= sizeof(adc_buffer)) {
        adc_buffer_wr_idx = 2;
        Serial.write((const uint8_t *)adc_buffer, sizeof(adc_buffer));
      }
    }
  }
}
Запустил:
upload_2020-1-11_15-17-41.png
Глянул ослом ноги i2c - дрыгают, но протокол обрывает - нет самого датчика на i2c.
Далее воткнул на соплях плату c INA226 в модуль MDK_USB_Dongle:
upload_2020-1-11_15-21-54.png
Паять грешно! :)

Проверил, что шина стала читаться и с ACK всё в порядке:
upload_2020-1-11_15-23-40.png
Включил китай-монитор COM-порта и наблюдаю нужные пакетики:
upload_2020-1-11_15-22-56.png
Вроде всё.
Далее хоть на питоне...
 

cheblin

Member
да, я не ардуинщик..
так оригинально отключать куски кода не умею... . всё так.
 

cheblin

Member
Офигиваю с дури компилятора кайла. На этот код
upload_2020-1-12_11-24-56.png

выдаёт ошибку.

upload_2020-1-12_11-27-11.png

требуя писать так
upload_2020-1-12_11-23-23.png

в то время как ВСЕ прочие С компиляторы прекрасно воспринимают этот код.

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

Тошниловка...
 
Сверху Снизу