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

UBIA - USB / BLE to I2C/SMBus Adapter.

pvvx

Активный участник сообщества
Несколько стандартных характеристик UUID для BLE.
Это не все...
 
У данного чипа (DS3231) беды в том, что он много жрет в качестве часов
Да и наплевать, зато он прост как тапок и хорошо изучен ардуинщиками :)
Мы же на нем не часы будем делать на постоянку, а учиться программировать шину I2c на TLSR8266!

Учебный материал должен быть максимально простым. Поэтому я и вспомнил про этот чип.
В нем есть все что надо для обучения:

0) Управление по I2c
1) Чтение регистров чипа
2) Запись регистров чипа
3) Вывод прерывания от будильника. :)
4) Легкий вывод понятной текстовой информации (время)


Где вы берете такую гадость?
Купил пучок когда разбирался с ардуиной. маме говорящие часы на ней и DFPlayer делал (управление два енкодера, большая встроенная библиотека аудиокниг) На алиэкспрессе их завались. Большая часть материалов в интернете озаглавленная "Часы на ардуине" собраны именно на ней.

Решение с часами находится в соседней теме.
Разберемся с этим контроллером, перейдем к тому. :)
 

pvvx

Активный участник сообщества
Т.е. вы типа этого ищите?

11.8 IIC
11.8.1 IIC Pin

Telink MCU embeds an IIC module. SDA and SCK line of the IIC module can be mapped to multiple groups (8261/8267/8269: 3 groups; 8266: 1 group) of GPIOs, as shown in the table below.
IIC pin mapping table
IC type IIC No.SDASCL
8261/8267/82691
2
3
PA3
PB6
PC0
PA4
PB7
PC1
82661PE7PF1
Since GPIOs of Telink MCU support multiplexed functions, to use IIC function, it’s needed to configure corresponding GPIO pins by invoking “i2c_pin_init ()” function. The function prototype is shown as below:
void i2c_pin_init(I2C_GPIO_GroupTypeDef i2c_pin_group)
Parameter Descripton
i2c_pin_groupGPIO pin group to be configured. It’s an enum-type value.
E.g.
i2c_pin_init(I2C_GPIO_GROUP_C0C1);
...
Ну такое в Application Note: Telink TLSR826x BLE SDK Developer Handbook
 

pvvx

Активный участник сообщества
Так-же в SDK есть примеры:
telink_ble_sdk_release_v3.3.0_20191012\vendor\826x_driver_test\app_i2c.c

Или надо всю документацию и примеры скопировать в форум?
 

pvvx

Активный участник сообщества
Т.к. в данных чипах нормальный i2c контролер, то всякие дуры-процедуры использовать не имеет смысла.
Максимум что можно использовать - это i2c_pin_init(). И то самому запрограммировать пины с нужными подтяжками проще.
И если идем на сон, то для некоторых чипов i2c желательно снять или изменить сопротивление подтяжек c X кОм на X МОм т.к. оно будет жрать.
А с контроллером i2c проще работать с его регистрами напрямую, т.к. вместо имен процедур их аргументы в том-же виде и кодировке лучше записывать напрямую прямо в регистры контроллера без посредников. Он достаточно "вумный" и оптимизированный. Это не STM с обрубками и errata.
 
Т.е. вы типа этого ищите?
Не. Я ищу то, что мне следует вписать в нижеследующий фрагмент javascript для того чтобы получить от чипа DS3231 припаянного к ногам SDA SCL модуля JDY-10 текущее время.
JavaScript:
...
ondata:(event)=>{ // событие возникающее при срабатывании characteristicvaluechanged
            log("OnData");
            let value = event.target.value.buffer ? event.target.value : new DataView(event.target.value);
            if(value.byteLength > 1) {
                let ds = value.getUint8(0);
                if(ds+2 >= value.byteLength) {
                    let idx = value.getUint8(1);
// тут мы начинаем обрабатывать команды ?????
                    switch(idx)
                    {
                        case 0x0c:
                            break;
                    }
                }
...
}
Тоесть нужен некоторый Розетский камень, который позволит приложить простенький код для ардуины к javascript необходимому для получения тех же данных от чипа подключенного к TSLR.
 

pvvx

Активный участник сообщества
Да и наплевать, зато он прост как тапок и хорошо изучен ардуинщиками :)
А у меня такого нет, т.е. есть где-то готовых платах разработки типа того века, если ещё не выбросил. Их что теперь сдувать от туда и на соплях припаивать?
 

pvvx

Активный участник сообщества
ondata:(event)=>{ // событие возникающее при срабатывании characteristicvaluechanged
Чтобы получить данные с i2c по началу надо инициализировать шину i2с на необходимую вас скорость - 2 мегабита потянет?
Потом создать запрос что вы хотите - читать или записывать или сразу одновременно писать значения и читать по i2c с чипа?
Как читать - циклически с каким периодом и как формировать выходные блоки данных в соответствие с выбранными вами интервалами соединения...
От каждой команды и придет событие подтверждения её исполнения и данные...
 
Хм. Процитирую сам себя "Стоп. стоп. Я понял что буду иметь дело с чем то вроде "удаленной" I2c шины, я туда пакеты, мне обратно пакеты." (c)
Раз шина еще не инициализирована, то где я оказываюсь в этом обработчике и что там могу делать?

Щас тогда попробую идентифицировать и выделить в отдельный метод код настройки шины из ваших js примеров ...
 

pvvx

Активный участник сообщества
Если работать с i2c без автоматов, то инициализация примерно такая:
Код:
function i2cDrvInit(clk){
    log('Send command#01: Init I2C/SMBUS CLK '+clk+' kHz...');
    let blk = new Uint8Array([6, 1, 0, 0, 255, 255, clk&0xff, (clk>>8)&0xff]);
    characteristicCache.writeValue(blk);
}
 

pvvx

Активный участник сообщества
Там много параметров, созданных для автоматической инициализации подключенных датчиков.
Когда происходит соединение с устройством, то включается пин подающий питание на датчик.
Инициализируется шина i2с, подаются стандартные команды SMBUS на сброс шины.
Далее, если заданы какие-то установки регистров - то они прописываются в датчик.
Из структуры берутся значения периодов и размеров блока передачи периодического опроса регистров датчика для формирования автоматического блока передачи.
Этим и управляет структура инициализации i2c. Имеет свойства записи в Flash для формирования устройства которое будет автоматически передавать данные при подключении уже без повтора всяких инициализаций...
 

pvvx

Активный участник сообщества
Если датчик имеет спящие режимы и подключен в питание на постоянку - тогда, обычно его надо разбудить перед работой (соединением по BLE) и закинуть в сон после.
Вот всё это и делает структура инициализации.
Но для вашего пример достаточно установить частоту clk и псё.
По этому сократим её, как дано выше.
 

pvvx

Активный участник сообщества
Так-же я не знаю как вам нравится писать в js.
characteristicCache.writeValue(blk).then(val.. и далее.. {});
Или через Async/await ?
Мои примеры писаны по самому примитивному... запрос-ответ.
 
когда частота установится, в ответ я наверняка получу какое то подтверждение? По всей видимости оно обладает кодом, который можно считать тут
JavaScript:
let idx = value.getUint8(1);
Так?

Поймав этот код(какой?), мне наверно следует как то получить адрес устройства на I2c и послать ему строку инициализации Ds3231 .
В примере для ардуины она выглядит так:
JavaScript:
Wire.write(0x0E); //выставляемся в 14й байт
Wire.write(B00000000); //сбрасываем контрольные регистры
Wire.write(B10001000); //выставляем 1 на статус OSF и En32kHz
Как выглядит аналог этой последовательности в вызове characteristicCache.writeValue(blk)? Так и слать побайтово?

Мои примеры писаны по самому примитивному...
Так и надо! чем проще тем лучше, нас могут читать люди для которых js это вообще темный лес.
 

pvvx

Активный участник сообщества
На i2cDrvInit(clk) вам в событие ondata:(event)=> свалится структура
Код:
typedef struct {
    uint8_t size;    //+0 размер данных пакета
    uint8_t cmd;    //+1 номер команды / тип пакета (=1)
    uint8_t pktcnt;      //+2 кол-во передаваемых значений из регистров в одном пакете передачи
    uint8_t multiplier; //+3 множитель периода опроса, time << multiplier
    uint16_t time;         //+4 период опроса регистров чтения в us
    uint16_t clk_khz;     //+6 частота i2c шины в kHz
    reg_wr_t init[MAX_INIT_REGS];
    reg_rd_t rd[MAX_READ_REGS];
    reg_wr_t slp[2];
} dev_i2c_cfg_t;
Далее что делать с вашим датчиком?
 
Инициализация
Код:
Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
Wire.write(0x0E); //выставляемся в 14й байт
Wire.write(B00000000); //сбрасываем контрольные регистры
Wire.write(B10001000); //выставляем 1 на статус OSF и En32kHz
Wire.endTransmission();
Получение данных

C:
 Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
   Wire.write(0x00); // start at register 0
   Wire.endTransmission();
   Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes
 
   if(Wire.available()) {
     seconds = Wire.read(); // get seconds
     minutes = Wire.read(); // get minutes
     hours   = Wire.read();   // get hours
     day     = Wire.read();
     date    = Wire.read();
     month   = Wire.read(); //temp month
     year    = Wire.read();
   }
 

pvvx

Активный участник сообщества
Если вернется cmd c 7-мым выставленным битом, то значит беда на шине i2c.

Инициализация
Получение данных
Это всё можно было описать в структуре инициализации на автомат получения ваших минут/секунд.
Но мы пойдем самым сложным путем - ближе к Arduino! :)

Вам как - читать по одному регистру или сразу всё скопом в одном блоке?
 

pvvx

Активный участник сообщества
JavaScript:
function ReadDS3231Data(dev_addr, data_len) {
/* typedef struct _i2c_utr_t {
    uint8_t size;    // размер пакета
    uint8_t cmd;    // номер команды / тип пакета (=0x0C)
    unsigned char mode;  // bit0..6: number wr_byte for new START (bit7: =1 - generate STOP/START)
    unsigned char rdlen; // bit0..6: number rd_byte (bit7: =1 - old read byte generate NACK, =0 - ACK)
    unsigned char wrdata[1..]; // i2c_addr_wr, wr_byte1, wr_byte2, wr_byte3, ... wr_byte126
} dev_i2c_utr_t; */
    log('Send command #0C: Read DS3231 Data...');
    let blk = new Uint8Array([0x05, 0x0c, 0x81, data_len&0x7f, (dev_addr<<1), 0]);
    characteristicCache.writeValue(blk);
}
 
Сверху Снизу