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

UBIA - USB / BLE to I2C/SMBus Adapter.

pvvx

Активный участник сообщества
Стоп. стоп. Я понял что буду иметь дело с чем то вроде "удаленной" I2c шины, я туда пакеты, мне обратно пакеты. Ведь запрограммировать сам чип на предобработку сигналов с акселлерометра мы не можем. или можем?
Вы пока не можете, я и другие могут.
Для этого надо написать несколько строк, а может и страницу текста на СИ под имеющийся SDK...
 

pvvx

Активный участник сообщества
теперь пытаюсь собрать самый минимальный пример, без графиков и в виде класса, чтобы было понятно где общий код, а где специфичный для каждого конкретного датчика. То что вы сделали конечно здорово и красиво но несколько затрудняет понимание происходящего в программе.
А вот это будет сложно, т.к. оно так выросло с самых малых начал моих ковыряний и изучения BLE совместно с чипами от Telink, путем наслоения и копи-паста предыдущего. Т.е. там много лишнего и наростов для тестов, а не для рабочего девайса.
Но выкинуть лишнее - это не заново с нуля...
 

pvvx

Активный участник сообщества
ээээ . а там есть c ?
А как-же без этого - все исходники приведены.
Ваша задача не сложнее чем её решение на ESP32. Во многом наверняка проще, т.к. не требуются поддержка многих интерфейсов необходимых для устройств работающих в сетях IP.
 

pvvx

Активный участник сообщества
В SDK у вас весь интерфейс с BLE – это две функции – callback: пришли данные, передать данные(ограниченный по размеру блок).
Всё остальное за вас делает SDK, стек BLE и прочее. Желательно понять что такое сервисы с UUID…
В принципе вам и события connect, disconnect и прочие не нужны.
Тупенькая программа:
По старту инициализировать датчик на шине i2c.
Через период считать данные с датчика и послать в функцию передачи.
Это всё, даже думать не о чем. Оно само разберется, если по принципу Arduino :)

Сложности возникают только в обеспечении минимального потребления устройством путем отключения CPU и всего что можно и как можно чаше. С этим уже связаны основные вопросы и алгоритмы их решений. Но вам то на потребление … если в качестве альтернативы в проекте используете ESP32 или Arduino :)
 
Ваша задача не сложнее чем её решение на ESP32.
С одним но очень серьезным для новичка "Но" никаких готовых библиотек для датчиков типа акселлерометра нет, надо ее написать самому, на примере какой либо библиотеки для ардуины. И надо понимать куда встроится со своими добавками в исходниках прошивки. А это тоже не тривиально.
 

pvvx

Активный участник сообщества
Есть и ещё более простой алгоритм:
Пишите данные с датчика в назначенный буфер в памяти для некоего назначенного "ящика с UUID" с атрибутами чтения.
Это как в USB.
Ящик считывает стандартное API в смарте или компе.
С одним но очень серьезным для новичка "Но" никаких готовых библиотек для датчиков типа акселлерометра нет, надо ее написать самому, на примере какой либо библиотеки для ардуины. И надо понимать куда встроится со своими добавками в исходниках прошивки. А это тоже не тривиально.
Дайте мне либу на имеющиеся у меня датчики.
Те, которые есть не работают или не выдают и 10 точек в сек.
И обычно гонят какю-то лажу и сбоят. На их переписывание уходит больше времени и сил, чем написать с нуля правильно.
 

pvvx

Активный участник сообщества
А исходники которые дают производители датчиков обычно примитивны. Но они работают в данном SDK.
От Arduino не работают, т.к. там C++. А на CPU без MMU C++ применять невозможно - это обязательный "эксепшн" по мере дефрагментации heap.
 

pvvx

Активный участник сообщества
И надо понимать куда встроится со своими добавками в исходниках прошивки. А это тоже не тривиально.
Для этого надо понять, что setup() назван user_init(), а loop() - main_loop().
Это очень тяжко для Ардуино-головного-мозгу.
Аналогично и с i2c. Просто выкинуты ненужные и непонятные никому из обывателей transmission stop/start и прочие изжитые аббревиатуры и ритуалы.

Где в эксплорере или компе setup() и loop() ?
 

pvvx

Активный участник сообщества
С одним но очень серьезным для новичка "Но" никаких готовых библиотек для датчиков типа акселлерометра нет, надо ее написать самому, на примере какой либо библиотеки для ардуины.
Для новичка или для программиста первым вопросом будет "что такое Arduino?".
Потом будут вопросы - где IDE и где SDK Developer Handbook?
На данный чип это все есть, в отличии, к примеру от ESP.
Потом обычно запрашивают "Конфигуратор" для типовых задач и настройки проекта, по типу Куба для STM.
Этого нет. Для BLE есть только у одного производителя и то по подписке...
 
Где в эксплорере или компе setup() и loop() ?
в експлорере setup в document.addEventListener('DOMContentLoaded', () => {}); loop на событиях по крупному счету висит.
В компе куча всяких автостартов, там обычно вирусы гнездятся. :)
Ардуиновский setup и loop, в теории, вещь полезная, ибо в норме они обычно вызываются из user_init() и main_loop() после того как внутренний код провел всю нужную инициализацию и до того как он-же подчистил за собой ошметки работы методов.

Для новичка или для программиста первым вопросом будет "что такое Arduino?".
Нет. первым вопрос тут будет "куда тут свой код писать".
 

pvvx

Активный участник сообщества
Ардуиновский setup и loop, в теории, вещь полезная, ибо в норме они обычно вызываются из user_init() и main_loop() после того как внутренний код провел всю нужную инициализацию и до того как он-же подчистил за собой ошметки работы методов.
А где в setup() ветка быстрого старта после микро-амперного сна чипа?
Ну там после 100..500 us после включения питаний доп. тактовых генераторов и CPU?
И если мне не надо "всю нужную инициализацию" - у меня всего мелкий датчик и от него надо передать пару байт на страницу в Web, тогда как?
Вот в упор не вижу во всем Arduino ни малейшего примера или привета с демкой передачи потока ADC на тупой график в Web. Что уж там говорить о каких-то подключаемых датчиках.
 

pvvx

Активный участник сообщества
Нет. первым вопрос тут будет "куда тут свой код писать".
Про это описано в SDK Developer Handbook.
Для разных нужд для оптимизации выпускают разные SDK и в каждом свои фичи.
На Arduino нет "Arduino Developer Handbook" - даже Google про это не знает.
Кроме того, по опыту, большинство, эдак 90% информации по либам и даже самой системе Arduino является закрытой, т.е. проприетарной.
А детские либы к ней - естественно все баговые - от куда у их писателей информация как работает та или иная версия Arduino.
 

pvvx

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

И о чем тут вообще разговор?
На UBIA есть вывод данных с акселерометра в web страничку. Для остального хлама этого нет.
 

pvvx

Активный участник сообщества
И никаких роутеров не требуется:
1615047642163.png
 
А где в setup() ветка быстрого старта после микро-амперного сна чипа?
А тут парадокс. У того же всеми ругаемого MS весь ASP.NET увешан евентами разных этапов загрузки страницы. До инициализации, после инициализации, до события, после события, перед уничтожением, после уничтожения :) . Возможно и у этих оно есть но они забыли об этом рассказать? Новичкам не надо, а бывалые не спрашивают.

Такая система создана для того, чтобы было побольше шума в форумах
Думаю скорее для того чтобы начинающие юзеры не смотрели в шоке на простыни непонятного английского текста и не говорили да ну их нафиг это слишком сложно... И надо отдать должное их подход сработал!
 
Вот вроде набросал темплейт шаблона обработки произвольного датчика. Гляньте плииз, все правильно или я что лишнее отрезал или оставил.
Вроде страничка корректно коннектится и дисконектится в characteristicvaluechanged какие то байтики бегают :)
Осталось разобраться как сам датчик программировать, по этому поводу у меня появилась идейка, в следующем сообщении расскажу.

JavaScript:
<html>
<body>
 <button onclick="ble.connect()">Connect</button>
 <button onclick="ble.disconnect()">Disconnect</button>
</body>
<script>
  var ble;
  function log(obj,type){console.log(obj)}
  document.addEventListener('DOMContentLoaded', () => {
      ble=new Ble({
          log,   // ссылка на 'местную' функцию лога. 
          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;
                    }
                }
            }
      }});
  });

// Все что ниже по тексту, весь этот класс, в дальнейшем, мы вынесем в отдельный подключаемый модуль ble.js
// Он в теории универсален для любых датчиков
class Ble
{
    devcnn = 0;
    deviceCache = null;
    characteristicCache = null;

    constructor(params) {
        this._log=params.log;
        this.ondata=params.ondata;
    }

    handleEvent(event)
    {
        switch(event.type)
        {
            case 'gattserverdisconnected':
                let device = event.target;
                if(this.devcnn != 0) {
                    this.log('"' + device.name + '" bluetooth device disconnected, trying to reconnect...');
                    this.connectDeviceAndCacheCharacteristic(device)
                    .then(characteristic => {
                        return this.startNotifications(characteristic)
                    })
                    .catch(error => this.log(error,'error'));
                }
                break;
            case 'characteristicvaluechanged':
                this.log('characteristicvaluechanged');
                if(this.ondata) this.ondata(event);
                break;
        }
    }

    connect() {
      return (this.deviceCache ? Promise.resolve(this.deviceCache) :
          this.requestBluetoothDevice()).then(
              device => this.connectDeviceAndCacheCharacteristic(device))
              .then(characteristic => this.startNotifications(characteristic))
        .catch(err => {
          this.log(err,'error');
        });
    }
    
    connectDeviceAndCacheCharacteristic(device) {
        if (device.gatt.connected && this.characteristicCache) {
          this.log("Reconnect ok"); 
          return Promise.resolve(this.characteristicCache);
        }
        this.log('Connecting to GATT server...');
        return device.gatt.connect().then(server => {
              this.log('GATT server connected, getting service...');
              return server.getPrimaryService(0xffe0);
              }).then(service => {
                this.log('Service found, getting characteristic...');
                return service.getCharacteristic(0xffe1);
                }).then(characteristic => {
                    this.log('Characteristic found');
                    this.characteristicCache = characteristic;
                    return this.characteristicCache;
                    });
    }

    startNotifications(characteristic) {
        this.log('Starting notifications...');
        return characteristic.startNotifications()
        .then(() => {
            this.log('Notifications started');
            characteristic.addEventListener('characteristicvaluechanged', this);
            this.devcnn = 1;
            this.stage_read = 0;
            setTimeout(()=>{this.SendWhoIs(this)}, 500);
        });
    }

    SendWhoIs(e){
        this.log('Send command #00: WhoIs?');
        this.characteristicCache.writeValue(new Uint8Array([0, 0]));
    }

    requestBluetoothDevice() {
        this.log('Requesting bluetooth device...');
        return navigator.bluetooth.requestDevice({
        filters: [{namePrefix: 'tBLE'}],
            optionalServices: ['0000ffe0-0000-1000-8000-00805f9b34fb', '0000ffe1-0000-1000-8000-00805f9b34fb']
        }).then(device => {
            this.log('"' + device.name + '" bluetooth device selected');
            this.deviceCache = device;
            this.deviceCache.addEventListener('gattserverdisconnected', this);
            return this.deviceCache;
        });
    }

    disconnect() {
        this.devcnn = 0;
        if (this.deviceCache) {
            this.log('Disconnecting from "' + this.deviceCache.name + '" bluetooth device...');
            this.deviceCache.removeEventListener('gattserverdisconnected', this);
            if (this.deviceCache.gatt.connected) {
                if (this.characteristicCache) {
                    this.characteristicCache.stopNotifications()
                    .then(_ => {
                        this.log('Notifications stopped');
                        this.characteristicCache.removeEventListener('characteristicvaluechanged', this);
                          if (this.deviceCache.gatt.connected) {
                            this.deviceCache.gatt.disconnect();
                            this.log('"' + this.deviceCache.name + '" bluetooth device disconnected');
                        }
                        this.deviceCache = null;
                    })
                    .catch(error => { this.log(error,'error');
                        if (this.characteristicCache) {
                            this.characteristicCache.removeEventListener('characteristicvaluechanged', this);
                            this.characteristicCache = null;
                        }
                        this.deviceCache = null;
                    });
                }
            }
        }
        else
        {
            this.log('"' + this.deviceCache.name + '" bluetooth device is already disconnected');
        }
    }

    log(o)
    {
        if(this._log) this._log(o);
    }
}
</script>
</html>
 
Теперь с датчиком. Практически у любого ардуинщика в загашнике есть такой замечательный модуль как DS3231. Ну да часики с будильником. В наших учебных целях он интересен тем, что подключается по шине I2c и при этом крайне прост в программировании. Может совместными усилиями прицепим его к выложенному выше примеру и можно будет его использовать как учебный блинк для UBIA ? Ну типа банальный вывод текущего времени из DS3231 на страничку.

Если чо, вот пример программирования этого датчика через Wire и даташит.
 

Вложения

pvvx

Активный участник сообщества
Теперь с датчиком. Практически у любого ардуинщика в загашнике есть такой замечательный модуль как DS3231. Ну да часики с будильником. В наших учебных целях он интересен тем, что подключается по шине I2c и при этом крайне прост в программировании. Может совместными усилиями прицепим его к выложенному выше примеру и можно будет его использовать как учебный блинк для UBIA ? Ну типа банальный вывод текущего времени из DS3231 на страничку.

Если чо, вот пример программирования этого датчика через Wire и даташит.
У данного чипа (DS3231) беды в том, что он много жрет в качестве часов. В активном режиме жрет более чем чип BLE.
Где вы берете такую гадость?

Ещё забыл - чтобы оно обеспечивало заявленные хар-ки требуется постоянная рекалибровка, что ещё жрет батарейку :)
 
Сверху Снизу