Berry i2c improvements (#11497)

* Berry i2c improvements

* fix

* unfix

Co-authored-by: Stephan Hadinger <stephan.hadinger@gmail.com>
This commit is contained in:
s-hadinger 2021-03-28 19:07:48 +02:00 committed by GitHub
parent e7a851f197
commit 1bd593eda3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 173 additions and 68 deletions

View File

@ -1843,6 +1843,104 @@ const bclosure load_closure = {
/*******************************************************************/
/********************************************************************
// tasmota.wire_scan(addr:int [, index:int]) -> wire1 or wire2 or nil
// scan for the first occurrence of the addr, starting with bus1 then bus2
// optional: skip if index is disabled via I2CEnable
"def wire_scan(addr,idx) "
// skip if the I2C index is disabled
"if idx != nil && !self.i2c_enabled(idx) return nil end "
"if self.wire1.detect(addr) return self.wire1 end "
"if self.wire2.detect(addr) return self.wire2 end "
"return nil "
"end "
********************************************************************/
/********************************************************************
** Solidified function: wire_scan
********************************************************************/
be_define_local_const_str(wire_scan_str_name, "wire_scan", -1623691416, 0, 9, 0);
be_define_local_const_str(wire_scan_str_source, "string", 398550328, 0, 6, 0);
be_define_local_const_str(wire_scan_str_0, "i2c_enabled", 218388101, 0, 11, 0);
be_define_local_const_str(wire_scan_str_1, "wire1", -1082245877, 0, 5, 0);
be_define_local_const_str(wire_scan_str_2, "detect", 8884370, 0, 6, 0);
be_define_local_const_str(wire_scan_str_3, "wire2", -1065468258, 0, 5, 0);
static const bvalue wire_scan_ktab[4] = {
{ { .s=be_local_const_str(wire_scan_str_0) }, BE_STRING},
{ { .s=be_local_const_str(wire_scan_str_1) }, BE_STRING},
{ { .s=be_local_const_str(wire_scan_str_2) }, BE_STRING},
{ { .s=be_local_const_str(wire_scan_str_3) }, BE_STRING},
};
static const uint32_t wire_scan_code[25] = {
0x4C0C0000, // 0000 LDNIL 3
0x200C0403, // 0001 NE R3 R2 R3
0x780E0005, // 0002 JMPF R3 #0009
0x8C0C0100, // 0003 GETMET R3 R0 R256
0x5C140400, // 0004 MOVE R5 R2
0x7C0C0400, // 0005 CALL R3 2
0x740E0001, // 0006 JMPT R3 #0009
0x4C0C0000, // 0007 LDNIL 3
0x80040600, // 0008 RET 1 R3
0x880C0101, // 0009 GETMBR R3 R0 R257
0x8C0C0702, // 000A GETMET R3 R3 R258
0x5C140200, // 000B MOVE R5 R1
0x7C0C0400, // 000C CALL R3 2
0x780E0001, // 000D JMPF R3 #0010
0x880C0101, // 000E GETMBR R3 R0 R257
0x80040600, // 000F RET 1 R3
0x880C0103, // 0010 GETMBR R3 R0 R259
0x8C0C0702, // 0011 GETMET R3 R3 R258
0x5C140200, // 0012 MOVE R5 R1
0x7C0C0400, // 0013 CALL R3 2
0x780E0001, // 0014 JMPF R3 #0017
0x880C0103, // 0015 GETMBR R3 R0 R259
0x80040600, // 0016 RET 1 R3
0x4C0C0000, // 0017 LDNIL 3
0x80040600, // 0018 RET 1 R3
};
static const bproto wire_scan_proto = {
NULL, // bgcobject *next
8, // type
GC_CONST, // marked
6, // nstack
0, // nupvals
3, // argc
0, // varg
NULL, // bgcobject *gray
NULL, // bupvaldesc *upvals
(bvalue*) &wire_scan_ktab, // ktab
NULL, // bproto **ptab
(binstruction*) &wire_scan_code, // code
be_local_const_str(wire_scan_str_name), // name
25, // codesize
4, // nconst
0, // nproto
be_local_const_str(wire_scan_str_source), // source
#if BE_DEBUG_RUNTIME_INFO /* debug information */
NULL, // lineinfo
0, // nlineinfo
#endif
#if BE_DEBUG_VAR_INFO
NULL, // varinfo
0, // nvarinfo
#endif
};
static const bclosure wire_scan_closure = {
NULL, // bgcobject *next
36, // type
GC_CONST, // marked
0, // nupvals
NULL, // bgcobject *gray
(bproto*) &wire_scan_proto, // proto
{ NULL } // upvals
};
/*******************************************************************/
/********************************************************************
@ -1858,6 +1956,8 @@ void be_load_tasmota_ntvlib(bvm *vm)
{ "_timers", NULL },
{ "_cmd", NULL },
{ "_drivers", NULL },
{ "wire1", NULL },
{ "wire2", NULL },
{ "get_free_heap", l_getFreeHeap },
{ "publish", l_publish },
{ "cmd", l_cmd },
@ -1902,6 +2002,7 @@ void be_load_tasmota_ntvlib(bvm *vm)
{ "event", (bntvfunc) &event_closure },
{ "add_driver", (bntvfunc) &add_driver_closure },
{ "load", (bntvfunc) &load_closure },
{ "wire_scan", (bntvfunc) &wire_scan_closure },
{ NULL, NULL }
};

View File

@ -212,7 +212,7 @@ const bclosure write_bytes_closure = {
void be_load_wirelib(bvm *vm)
{
static const bnfuncinfo members[] = {
{ "_bus", NULL }, // bus number
{ "bus", NULL }, // bus number
{ "init", b_wire_init },
{ "_begin_transmission", b_wire_begintransmission },
{ "_end_transmission", b_wire_endtransmission },

View File

@ -6,62 +6,53 @@
-#
class MPU6886 : Driver
var enabled, wire
var wire #- if wire == nil then the module is not initialized -#
var gres, ares
var accel, gyro
def init()
self.enabled = false
if tasmota.i2c_enabled(58) || 1
var bus = 1
if wire1.detect(0x68)
self.wire = wire1
elif wire2.detect(0x68)
self.wire = wire2
bus = 2
end
self.wire = tasmota.wire_scan(0x68, 58)
if self.wire
var v = self.wire.read(0x68,0x75,1)
if v != 0x19 return end #- wrong device -#
if self.wire
var v = self.wire.read(0x68,0x75,1)
if v != 0x19 return end #- wrong device -#
self.wire.write(0x68, 0x6B, 0, 1)
tasmota.delay(10)
self.wire.write(0x68, 0x6B, 1<<7, 1) # MPU6886_PWR_MGMT_1
tasmota.delay(10)
self.wire.write(0x68, 0x6B, 1<<0, 1) # MPU6886_PWR_MGMT_1
tasmota.delay(10)
self.wire.write(0x68, 0x1C, 0x10, 1) # MPU6886_ACCEL_CONFIG - AFS_8G
tasmota.delay(1)
self.wire.write(0x68, 0x1B, 0x18, 1) # MPU6886_GYRO_CONFIG - GFS_2000DPS
tasmota.delay(1)
self.wire.write(0x68, 0x1A, 0x01, 1) # MPU6886_CONFIG
tasmota.delay(1)
self.wire.write(0x68, 0x19, 0x05, 1) # MPU6886_SMPLRT_DIV
tasmota.delay(1)
self.wire.write(0x68, 0x38, 0x00, 1) # MPU6886_INT_ENABLE
tasmota.delay(1)
self.wire.write(0x68, 0x1D, 0x00, 1) # MPU6886_ACCEL_CONFIG2
tasmota.delay(1)
self.wire.write(0x68, 0x6A, 0x00, 1) # MPU6886_USER_CTRL
tasmota.delay(1)
self.wire.write(0x68, 0x23, 0x00, 1) # MPU6886_FIFO_EN
tasmota.delay(1)
self.wire.write(0x68, 0x37, 0x22, 1) # MPU6886_INT_PIN_CFG
tasmota.delay(1)
self.wire.write(0x68, 0x38, 0x01, 1) # MPU6886_INT_ENABLE
tasmota.delay(100)
self.wire.write(0x68, 0x6B, 0, 1)
tasmota.delay(10)
self.wire.write(0x68, 0x6B, 1<<7, 1) # MPU6886_PWR_MGMT_1
tasmota.delay(10)
self.wire.write(0x68, 0x6B, 1<<0, 1) # MPU6886_PWR_MGMT_1
tasmota.delay(10)
self.wire.write(0x68, 0x1C, 0x10, 1) # MPU6886_ACCEL_CONFIG - AFS_8G
tasmota.delay(1)
self.wire.write(0x68, 0x1B, 0x18, 1) # MPU6886_GYRO_CONFIG - GFS_2000DPS
tasmota.delay(1)
self.wire.write(0x68, 0x1A, 0x01, 1) # MPU6886_CONFIG
tasmota.delay(1)
self.wire.write(0x68, 0x19, 0x05, 1) # MPU6886_SMPLRT_DIV
tasmota.delay(1)
self.wire.write(0x68, 0x38, 0x00, 1) # MPU6886_INT_ENABLE
tasmota.delay(1)
self.wire.write(0x68, 0x1D, 0x00, 1) # MPU6886_ACCEL_CONFIG2
tasmota.delay(1)
self.wire.write(0x68, 0x6A, 0x00, 1) # MPU6886_USER_CTRL
tasmota.delay(1)
self.wire.write(0x68, 0x23, 0x00, 1) # MPU6886_FIFO_EN
tasmota.delay(1)
self.wire.write(0x68, 0x37, 0x22, 1) # MPU6886_INT_PIN_CFG
tasmota.delay(1)
self.wire.write(0x68, 0x38, 0x01, 1) # MPU6886_INT_ENABLE
tasmota.delay(100)
self.enabled = true
self.gres = 2000.0/32768.0
self.ares = 8.0/32678.0
print("I2C: MPU6886 detected on bus "+str(bus))
end
self.gres = 2000.0/32768.0
self.ares = 8.0/32678.0
print("I2C: MPU6886 detected on bus "+str(self.wire.bus))
end
end
#- returns a list of 3 axis, float as g acceleration -#
def read_accel()
if !self.wire return nil end #- exit if not initialized -#
var b = self.wire.read_bytes(0x68,0x3B,6)
var a1 = b.get(0,-2)
if a1 >= 0x8000 a1 -= 0x10000 end
@ -75,6 +66,7 @@ class MPU6886 : Driver
#- returns a list of 3 gyroscopes, int as dps (degree per second) -#
def read_gyro()
if !self.wire return nil end #- exit if not initialized -#
var b = self.wire.read_bytes(0x68,0x43,6)
var g1 = b.get(0,-2)
if g1 >= 0x8000 g1 -= 0x10000 end
@ -88,17 +80,19 @@ class MPU6886 : Driver
#- trigger a read every second -#
def every_second()
if !self.wire return nil end #- exit if not initialized -#
self.read_accel()
self.read_gyro()
end
#- display sensor value in the web UI -#
def web_sensor()
if !self.wire return nil end #- exit if not initialized -#
import string
var msg = string.format(
"{s}MPU6886 acc_x{m}%f G{e}"..
"{s}MPU6886 acc_y{m}%f G{e}"..
"{s}MPU6886 acc_z{m}%f G{e}"..
"{s}MPU6886 acc_x{m}%.3f G{e}"..
"{s}MPU6886 acc_y{m}%.3f G{e}"..
"{s}MPU6886 acc_z{m}%.3f G{e}"..
"{s}MPU6886 gyr_x{m}%i dps{e}"..
"{s}MPU6886 gyr_y{m}%i dps{e}"..
"{s}MPU6886 gyr_z{m}%i dps{e}",
@ -108,6 +102,7 @@ class MPU6886 : Driver
#- add sensor value to teleperiod -#
def json_append()
if !self.wire return nil end #- exit if not initialized -#
import string
var ax = int(self.accel[0] * 1000)
var ay = int(self.accel[1] * 1000)
@ -118,5 +113,5 @@ class MPU6886 : Driver
end
end
mpu = MPU6886()
tasmota.add_driver(mpu)
mpu6886 = MPU6886()
tasmota.add_driver(mpu6886)

View File

@ -23,21 +23,21 @@
#include <berry.h>
#include <Wire.h>
// read the `_bus` attribute and return `Wire` or `Wire1`
// read the `bus` attribute and return `Wire` or `Wire1`
TwoWire & getWire(bvm *vm);
TwoWire & getWire(bvm *vm) {
be_getmember(vm, 1, "_bus");
int32_t bus = be_toint(vm, -1);
be_getmember(vm, 1, "bus");
int32_t bus = be_toint(vm, -1); // bus is 1 or 2
be_pop(vm, 1);
if (0 == bus) {
if (2 != bus) {
return Wire;
} else {
return Wire1;
}
}
int32_t getBus(bvm *vm);
int32_t getBus(bvm *vm); // 1 or 2
int32_t getBus(bvm *vm) {
be_getmember(vm, 1, "_bus");
be_getmember(vm, 1, "bus");
int32_t bus = be_toint(vm, -1);
be_pop(vm, 1);
return bus;
@ -57,15 +57,15 @@ extern "C" {
int32_t b_wire_init(struct bvm *vm);
int32_t b_wire_init(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
int32_t bus = 0;
int32_t bus = 1;
if (top > 1 && be_isint(vm, 2)) {
bus = be_toint(vm, 2);
if (bus < 0) { bus = 0; }
if (bus > 1) { bus = 1; }
if (bus < 1) { bus = 1; }
if (bus > 2) { bus = 2; }
}
// store bus in instance
be_pushint(vm, bus);
be_setmember(vm, 1, "_bus");
be_setmember(vm, 1, "bus");
be_return_nil(vm);
}
@ -193,7 +193,7 @@ extern "C" {
int32_t b_wire_validwrite(struct bvm *vm);
int32_t b_wire_validwrite(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
int32_t bus = getBus(vm);
int32_t bus = getBus(vm) - 1; // 0 or 1
if (top == 5 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5)) {
uint8_t addr = be_toint(vm, 2);
uint8_t reg = be_toint(vm, 3);
@ -210,7 +210,7 @@ extern "C" {
int32_t b_wire_validread(struct bvm *vm);
int32_t b_wire_validread(struct bvm *vm) {
int32_t top = be_top(vm); // Get the number of arguments
int32_t bus = getBus(vm);
int32_t bus = getBus(vm) - 1; // 0 or 1
if (top == 4 && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4)) {
uint8_t addr = be_toint(vm, 2);
uint8_t reg = be_toint(vm, 3);

View File

@ -284,6 +284,17 @@ const char berry_prog[] =
// "end "
// "end "
// // tasmota.wire_scan(addr:int [, index:int]) -> wire1 or wire2 or nil
// // scan for the first occurrence of the addr, starting with bus1 then bus2
// // optional: skip if index is disabled via I2CEnable
// "def wire_scan(addr,idx) "
// // skip if the I2C index is disabled
// "if idx != nil && !self.i2c_enabled(idx) return nil end "
// "if self.wire1.detect(addr) return self.wire1 end "
// "if self.wire2.detect(addr) return self.wire2 end "
// "return nil "
// "end "
"end "
// Instantiate tasmota object
@ -314,12 +325,10 @@ const char berry_prog[] =
// "end "
// "end "
"wire = Wire(0) "
"wire1 = wire "
"wire2 = Wire(1) "
// try to load "/autoexec.be"
// "try compile('/autoexec.be','file')() except .. log('BRY: no /autoexec.bat file') end "
"tasmota.wire1 = Wire(1) "
"tasmota.wire2 = Wire(2) "
"wire1 = tasmota.wire1 "
"wire2 = tasmota.wire2 "
;
const char berry_autoexec[] =