• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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...
 
Сверху Снизу