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

UBIA - USB / BLE to I2C/SMBus Adapter.

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

function ReadDS3231Data(dev_addr, data_len) {
А как получить адрес устройства на шине?

let blk = new Uint8Array([0x05, 0x0c, 0x81, data_len&0x7f, (dev_addr<<1), 0]);
[0x05, 0x0c, 0x81, data_len&0x7f, (dev_addr<<1), 0]) это описание структуры dev_i2c_utr_t в виде массива байт?
 

pvvx

Активный участник сообщества
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();
   }
В документации значится совершенно другой тип работы с DS3231.
1615106512767.png
Т.е. вы меня обманули и ваш "скетч" с ошибками.
 

pvvx

Активный участник сообщества
JavaScript:
function ReadDS3231Data(dev_addr, start_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([0x04, 0x0c, 0x01, (data_len&0x7f) | 0x80, (dev_addr << 1) & 0xfe , start_addr & 0xff]);
    characteristicCache.writeValue(blk);
}
Ответ придет в виде блока с байтами:
  • размер блока данных (= data_len + 2),
  • номер команды (=0x0С)
  • адрес устройства на шине ш2с ( = dev_addr)
  • кол-во считанных байт (= data_len)
  • массив данных[data_len]
Каюсь не проверял. Сам я готовой либой пользовался в свое время.
Этот пример взял отсюда - http://knodit.blogspot.com/2014/05/arduino-ds3231-i2c-wire.html
Там же написано "Arduino" !
Этим всё сказано.
У меня тоже могут быть ошибки, т.к. надо вспоминать что там понаписано и ещё заочно писать вам код без возможности проверки...
 
Код:
/* typedef struct _i2c_utr_t {
    uint8_t size;    // размер пакета
Как я понял, размер пакета не считая самого size и следующего за ним
cmd ?

У меня тоже могут быть ошибки, т.к. надо вспоминать что там понаписано и ещё заочно писать вам код без возможности проверки...
Но проблем. Проверю протестирую - что не получится спрошу.
 

pvvx

Активный участник сообщества
Код:
/* typedef struct _i2c_utr_t {
    uint8_t size;    // размер пакета
Как я понял, размер пакета не считая самого size и следующего за ним
cmd ?
Вроде, на 90%, точнее не помню - надо глядеть исходники... :) уже более года прошло как там копался.

Есть недоделка, т.к. не было нужно - это включение/выключение опции clock stretching на clk шины i2с.
Нужно где-то всунуть бит и приписать установку/сброс бита FLD_I2C_HOLD_MASTER -> BM_SET(reg_i2c_mode, FLD_I2C_MODE_MASTER | FLD_I2C_HOLD_MASTER); // enable master mode.
Оно не всегда и не для всех датчиков нужно, но иногда надоть...
 
function ReadDS3231Data(dev_addr, start_addr, data_len) {
а как узнать dev_addr?
что такое start_addr?

И мы не рассмотрели операцию записи в регистры. ну первоначальную. настройку DS3231
Код:
Wire.write(0x0E); //выставляемся в 14й байт 
Wire.write(B00000000); //сбрасываем контрольные регистры 
Wire.write(B10001000); //выставляем 1 на статус OSF и En32kHz
 

pvvx

Активный участник сообщества
Залил в UNO. Работает вроде(год я тогда не выставлял). к слову и врут не сильно, наверно с полгода пролежали без батареи, и ставил я их тогда на глаз.
Посмотреть вложение 10740

температура следует за пальцем.
Та им пофигу - ну не будет другое устройство совместно на шине работать т.к. SDA и SCL будут занята часами... Какая разница то Ардуинщикам?
 

pvvx

Активный участник сообщества
а как узнать dev_addr?
что такое start_addr?
На картинке в PDF написано:
<SLAVE ADDRESS> - dev_addr
<WORD ADDRESS> - start_addr

И мы не рассмотрели операцию записи в регистры. ну первоначальную. настройку DS3231
JavaScript:
function WriteDS3231Data(dev_addr, start_addr, data) {
    log('Send command #0C: Write DS3231 Data...');
    let blk = new Uint8Array(data.byteLength+6);
blk[0] = data.byteLength+4;
blk[1] = 0x0C;
blk[2] = 0x00;
blk[3] = 0x00;
blk[4] = (dev_addr << 1) & 0xfe;
blk[5] = start_addr & 0xff;
blk.set(data, 6);
    characteristicCache.writeValue(blk);
}
Тут, в редакторе форума нет форматирования и очень тяжко писать код :)
 

pvvx

Активный участник сообщества
Работает вроде(год я тогда не выставлял). к слову и врут не сильно, наверно с полгода пролежали без батареи, и ставил я их тогда на глаз.
Т.е. время они считали питаясь святым духом?
Данный чип работает до пары дней от 1 Фарады, а во всех современных устройствах ставят 0.15..0.3 Фарады на мало вольт и они тянут недели пока пользователь меняет основную батарейку.
А питание от батареек часов перестали использовать в том веке.
В UNO производителя чипа давно не существует... Где вы такой антиквариат откапали?
Когда перейдем на программирование ламп? У меня есть антикварный телевизор выпуска 50-х (из тех почему называлось голубой экран и с защитным стеклом от взрыва...)- надо как-то ему сигнал в антенну спрограммировать...
 
Тут, в редакторе форума нет форматирования и очень тяжко писать код
Я в Visual Studio Code пишу , а потом сюда копипащу.

Т.е. время они считали питаясь святым духом?
Там ионистор снизу приклеен,


Данный чип работает до пары дней
Ну не полгода, но 4 месяца точно. Последняя дата изменения в проекте 24.11.20. С тех пор плата на полке и валяется.
Где вы такой антиквариат откапали?
Самую первую купил с полгода назад в робошопе на Площади Восстания. Там и сейчас таких много. Ну потом еще поднабрал на али кучку, только мелких 3 вольтовых про.
из тех почему называлось голубой экран и с защитным стеклом от взрыва...
Там вода набиралась в линзу, ну и свет от трубки был с характерным голубоватым отливом(комнату заливал сине-голубым светом. Был у меня такой... :)
надо как-то ему сигнал в антенну спрограммировать...
Легко. В простейшем варианте вам надо раздобыть на помойке ВЧ модуль от видеомагнитофона ВМ-12... :)
 

pvvx

Активный участник сообщества
Там ионистор снизу приклеен,

Ну не полгода, но 4 месяца точно. Последняя дата изменения в проекте 24.11.20. С тех пор плата на полке и валяется.
Значит вас обманули и подсунули эмулятор DS3231 на каком современном китайском кристалле. Сверьте характеристики с даташитом.
И телевизор с защитным стеклом - это следующая модель, без линзы, но на кинескопе нет бандажной ленты. Не додумались ещё...
 

pvvx

Активный участник сообщества
1615121945566.png
И в данной табличке и вообще в PDF стесняются написать истинное потребление данных часов от батарейки.
А оно составляет ток утечек, счет часов и выполнение процедуры коррекции от температуры которая и выжирает батарейку...
Указан ток при снятии показаний температуры и он больше среднего тока к примеру Xiaomi термометра с LCD на CR3032.
 

pvvx

Активный участник сообщества
Есть отсылка:
Note 5: Current is the averaged input current, which includes the temperature conversion current.
А далее берете расчет 1 Ф заряженная на 3.3В и считаете среднее время работы...
Давно, когда они появились я поставил 1Ф в надежде что оно будет держать отключение на нерабочие дни. Но вышел фиг-вам.
 

pvvx

Активный участник сообщества
Соответственно все эти микросхемы и пошли на рынок Arduino. Куда же ещё такое девать?
 
Давно, когда они появились я поставил 1Ф в надежде что оно будет держать отключение на нерабочие дни. Но вышел фиг-вам.
Хм. Озадачили.... Гы! Дошло, вот так мифы и создаются! :))) Посмотрите на дату и время моего сообщения и время в логе на скриншоте . Догадались? А дата то мне действительно была не нужна (не проговаривалась часами) и я ее не выставлял в коде....
Я проводил свои тесты в 12:00, по всей видимости это время которое устанавливается в часах по умолчанию
По теме, вчера было не до этого, сегодня продолжу запускать чип (шину i2c буду пытаться программировать впервые в жизни :)).

Куда же ещё такое девать?
Туда куда мы ее и применяем - в учебные цели.
 
На всякий случай напомню, мы пытаемся эмулировать такую последовательность операторов Ардуино
JavaScript:
/* 
   Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
   Wire.write(0x0E); // как я понял это регистр в который надо писать?
   Wire.write(B00000000); // посылает в регистр 0; 
   Wire.write(B10001000); // посылает в тот же регистр 0xb 10001000 ?
   ... 
   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
*/

Код модуля Ble.js не привожу он не изменился и вроде корректно работает. Функцию log тоже упущу, она просто выводит лог.
Вот новый класс, описывающий модуль Ds3231.

JavaScript:
class ds3231
{
    dev_addr = 104;// 0x68;
    constructor(params) {
        this._log=params.log;
    }
    Read(event,data_len) 
    {
        let blk = new Uint8Array([0x05, 0x0c, 0x81, data_len&0x7f, (this.dev_addr<<1), 0]);
        this.log(blk,'dout');
        event.ble.characteristicCache.writeValue(blk);
    }
    Write(event,start_addr, data) 
    {
        let data_len = data.byteLength?data.byteLength+6:7;
        let blk = new Uint8Array(data_len);
        blk.set([data.byteLength+4,0x0C,0x0,0x0,(this.dev_addr << 1) & 0xfe,start_addr & 0xff, data]);
        this.log(blk,'dout');
        event.ble.characteristicCache.writeValue(blk);
    }
    log(o,t){if(this._log) this._log(o,t);}
}
Вот основной скрипт.

JavaScript:
document.addEventListener('DOMContentLoaded', () => {
    sensor = new ds3231({log});
    ble=new Ble({
        log, 
        ondata:(event)=>{ // срабатывание characteristicvaluechanged
          let value = event.target.value.buffer ? event.target.value : new DataView(event.target.value);
          log(value,'din');
          if(value.byteLength > 1) {
              let ds = value.getUint8(0);
              if(ds+2 >= value.byteLength) {
                  let idx = value.getUint8(1);
                  switch(idx)
                  {
                      case 0x0:
                          log('Инициализируем I2c шину');
                          event.ble.i2cDrvInit(1);
                          break;
                      case 0x81:
                          log('Отправляю аналог команд  Wire.write(0x0E);Wire.write(B00000000)');
                          sensor.Write(event,0x0e,0);
                          init_stage=1;
                          break;
                      case 0x8C:
                          switch(init_stage)
                          {
                              case 1:
                                  log('Отправляю аналог команд  Wire.write(0x0E);Wire.write(B10001000)');
                                  sensor.Write(event,0x0e,0b10001000);
                                  init_stage=2;
                                  break;
                              case 2:
                                  log('Отправляю аналог команд  Wire.write(0x00); Wire.requestFrom(DS3231_I2C_ADDRESS, 7);');
                                  sensor.Read(event,7);
                                  init_stage=3;
                                  break;
                          }
                          break;
                  }
              }
          }
    }});
});
Вот что выводится в лог. То есть работа застревает на чтении данных из ds3231

JavaScript:
/*
Connecting to GATT server...
GATT server connected, getting service...
Service found, getting characteristic...
Characteristic found
Starting notifications...
Notifications started
Send command #00: WhoIs?
(3) [">> ", "0x00", "0x00"]
characteristicvaluechanged
(7) ["<< ", "0x04", "0x00", "0x21", "0x10", "0x08", "0x00"]
Инициализируем I2c шину
Send command#01: Init I2C/SMBUS CLK 1 kHz...
(9) [">> ", "0x06", "0x01", "0x00", "0x00", "0xff", "0xff", "0x01", "0x00"]
characteristicvaluechanged
(3) ["<< ", "0x00", "0x81"]
Отправляю аналог команд  Wire.write(0x0E);Wire.write(B00000000)
(8) [">> ", "0x00", "0x0c", "0x00", "0x00", "0xd0", "0x0e", "0x00"]
characteristicvaluechanged
(3) ["<< ", "0x00", "0x8c"]
Отправляю аналог команд  Wire.write(0x0E);Wire.write(B10001000)
(8) [">> ", "0x00", "0x0c", "0x00", "0x00", "0xd0", "0x0e", "0x88"]
characteristicvaluechanged
(3) ["<< ", "0x00", "0x8c"]
Отправляю аналог команд  Wire.write(0x00); Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
(7) [">> ", "0x05", "0x0c", "0x81", "0x07", "0xd0", "0x00"]
...
больше ничего не происходит, при перезапуске опять доходит до этого места и висит.  
*/
 

pvvx

Активный участник сообщества
Почему CLK 1 кГц?
Ответ инициализации - 0x81 -> error
Команда записи "Отправляю аналог команд Wire.write(0x0E);Wire.write(B00000000)" передает блок с нулевой диной, ответ -> 0x8c - error.
И так далее.
Борьба с js...
 
Сверху Снизу