Luatos Air700 changes the BL0942 serial port baud rate

LuatOs changes the module serial port baud rate for reference

luatos changes the AIR530 serial port baud rate

BL0942 default serial port baud rate can be set to 9600bps by connecting the SCLK_BPS pin to a 3.3V power supply

But if you adjust to 38400bps, you need to modify the 0x19 register

Special register description of bl0942 v1.06 version, please note that there are errors in the special register description of earlier versions

Complete code

main.lua

-- LuaTools requires two pieces of information, PROJECT and VERSION
PROJECT = "EMQX_Plug"
VERSION = "1.0.1"

--[[
This demo requires the mqtt library, which is available on most devices that can connect to the Internet.
mqtt is also a built-in library, no need to require
]]

-- sys library is standard
_G.sys = require("sys")
--[[Special note, the following statements are required to use the mqtt library]]
_G.sysplus = require("sysplus")

-- Automatic low power consumption, light sleep mode
-- Air780E supports uart wake-up and network data wake-up, but you need to disconnect the USB, or pm.power(pm.USB, false), but you can't see the log in this way.
-- pm.request(pm.LIGHT)

-- Serial port ID, serial port read buffer
local bl0942 = require "bl0942"
local UART_ID1, UART1receQueue = 1, {}
local uartimeout, UART1recvReady = 25,"UART_RECV_ID1"


local RD_SPECIAL_REGISTER_FLAG=0
local RD_DATA_REGISTER_FLAG=0
local BAUD_CHANGED_FLAG=0
local LED = gpio.setup(31, 1, gpio.PULLUP)
local RELAY = gpio.setup(9, 1, gpio.PULLUP)
LED(1)


if wdt then
    --Add a hard dog to prevent the program from freezing and enable this feature on supported devices
    wdt.init(9000)--Initialize watchdog set to 9s
    sys.timerLoopStart(wdt.feed, 3000)--feed the dog once every 3 seconds
end



--The most commonly used 115200 8N1
local result1 = uart.setup(
    UART_ID1,--serial port id
    9600,--baud rate
    8,--data bits
    1--Stop bit
)
print(_VERSION)

sys.taskInit(function()
        log.info("Initialization","bl0942 software reset")
        BL0942_Write(UART_ID1,bl0942.SOFT_RESET,0x5A,0x5A,0x5A)
        sys.wait(100)
        --The following code sets the anti-creep threshold register to ensure that the electrical energy data will not accumulate noise and form negative values.
        BL0942_Write(UART_ID1,bl0942.USR_WRPROT,0x55,0x00,0x00)
        BL0942_Write(UART_ID1,bl0942.WA_CREEP,0x33,0x00,0x00)
                
       --The following changes the serial port baud rate
        BL0942_Write(UART_ID1,bl0942.MODE,0x87,0x03,0x00)
        BSP_FLAG=1
        uart.write(UART_ID1," ")--trigger the sent event of uart.on--trigger the sent event of uart.on
        print("GPS serial port baud rate has been changed")
end)


  uart.on(UART_ID1, "sent", function(uid)
      if BSP_FLAG==1 then
          -- uart.close(UART_ID1)--Commenting out this code can also change the baud rate
          result1 = uart.setup(
                   UART_ID1,--serial port id
                   38400,--Baud rate
                   8,--data bits
                   1--Stop bit
            )
         print("The Air700 UART1 serial port baud rate has been changed")
         BL0942_Write(UART_ID1,bl0942.USR_WRPROT,0xff,0x00,0x00)
        sys.publish("38400")
        BSP_FLAG=0
        BAUD_CHANGED_FLAG=1
    end
end)

sys.subscribe("38400",function()
     uart.on(UART_ID1, "receive", function(uid, length)
       local s
       while true do--guarantee no packet loss after reading
         s = uart.read(uid, length)
         if #s == 0 then break end
           table.insert(UART1receQueue, s)
         end
      sys.timerStart(sys.publish, uartimeout, UART1recvReady)
    end)
end)

sys.subscribe(UART1recvReady, function()
       
    if (RD_SPECIAL_REGISTER_FLAG==1) then
        local m={}
        local strRe = table.concat(UART1receQueue)
        if (#strRe)>4 then -- There may be 23 bytes of all-electric parameter data packets mixed in, which must be eliminated
            return --Reading a single register generally returns 3 bytes
        end
        -- log.info("Special register",#strRe)
        UART1receQueue = {}
        RD_SPECIAL_REGISTER_FLAG=0
        m[1]=string.byte(strRe,1)
        m[2]=string.byte(strRe,2)
        m[3]=string.byte(strRe,3)
        -- print(m[1],m[2],m[3])
        local m_temp = string.char(m[1],m[2],m[3])
        local mode=string.unpack("i3", m_temp)
        print(string.format("MODE=%d",mode))
  end

  if (RD_DATA_REGISTER_FLAG==1) then
    local v,c,e={},{},{}
    local vol,cur,engerywat
    -- local w,f={},{}
    -- local freq,engery
    local strDA = table.concat(UART1receQueue)
    if (#strDA)<23 then --Avoid parsing and reading register data
        return
    end
    UART1receQueue = {}
    RD_DATA_REGISTER_FLAG=0
    
    c[1]=string.byte(strDA,2)
    c[2]=string.byte(strDA,3)
    c[3]=string.byte(strDA,4)

    v[1]=string.byte(strDA,5)
    v[2]=string.byte(strDA,6)
    v[3]=string.byte(strDA,7)

    e[1]=string.byte(strDA,14)
    e[2]=string.byte(strDA,15)
    e[3]=string.byte(strDA,16)
    
    local cur_temp = string.char(c[1],c[2],c[3])
    local vol_temp = string.char(v[1],v[2],v[3])
    local ene_temp = string.char(e[1],e[2],e[3])
    -- local wat_temp = string.char(w[1],w[2],w[3])
    -- local freq_temp = string.char(f[1],f[2],f[3])
    
    local cur = string.unpack("i3", cur_temp)
    local vol = string.unpack("i3", vol_temp)
    local energy= string.unpack("i3", ene_temp)
    -- print(string.format("energy=%d",energy))
    -- local wat = string.unpack("i3", wat_temp)
    -- local freq = string.unpack("i3",freq_temp)

     pub_vol=(vol*V_CONSTANT)/V_DENO
     pub_cur=(cur*VREF/I_DENO)*1000
     pub_energy=(energy*E_PER_PLUSE)
        
     print(string.format("Current=%.1fmA Voltage=%.1fV Electricity=%0.2f degree ",pub_cur,pub_vol,pub_energy))
    -- print(string.format("Current=%0.2fA Voltage=%.1fV Power=%0.1fW Electricity=%0.2f degree Frequency=%0.1fHz",Current,Voltage,Energy,Wat,Freq) )
   end
end)
local cnt = 0

sys.timerLoopStart(function()
      if BAUD_CHANGED_FLAG==1 then
        uartimeout=25
        BL0942_Read(UART_ID1,0xAA)--V_RMS 0xAA bl0942.V_RMS Read the full electrical parameter data packet
        RD_DATA_REGISTER_FLAG=1
        RD_SPECIAL_REGISTER_FLAG=0
    end
end, 1000)

sys.timerLoopStart(function()
    if BAUD_CHANGED_FLAG==1 then
      uartimeout=5
      BL0942_Read(UART_ID1,bl0942.MODE) --Read 0x19 user mode selection register
      RD_SPECIAL_REGISTER_FLAG=1
      RD_DATA_REGISTER_FLAG=0
    end
end, 2400)

--User code ended---------------------------------------------------------- -
-- It always ends with this sentence
sys.run()
-- Do not add any statements after sys.run()!!!!!

bl0942.lua

local sys = require "sys"

 VREF = 1.218
 V_DENO =1842052.2
 V_CONSTANT=121.8
 I_DENO =504863.7 --305978*(3.3*1000)/2000
 DOUBLE_FS =1000000.0
 POWER_COEFF=148.3524 --1.218*1.218*20*5
 P_DENO =145317.645 --3537*(3.3*1000/2000)*0.0249*1000
 E_PER_PLUSE=0.000118942

 bl0942= setmetatable({}, {
    __index = {
        WRITE_HEAD = 0xA8,
        READ_HEAD = 0x58,
        I_WAVE = 0x01, --Current waveform register, signed
        V_WAVE = 0x02, --Voltage waveform register, signed
        I_RMS = 0x03, --current effective value register, unsigned
        V_RMS = 0x04, --voltage effective value register, unsigned
        I_FAST_RMS = 0x05, --current fast RMS register, unsigned
        WATT = 0x06, --active power register, signed
        CF_CNT = 0x07, --Active energy pulse count register, unsigned
        FREQ = 0x08, --line voltage frequency register
        STATUS = 0x09, --status register

        ----------User operation register (read and write)--------------------
        I_RMSOS = 0x12, --current effective value small signal correction register
        WA_CREEP = 0x14, --Active power anti-subscription register
        I_FAST_RMS_TH = 0x15, --current fast RMS threshold register
        I_FAST_RMS_CYC= 0x16, --current fast effective value refresh cycle register
        FREQ_CYC = 0x17, --Line voltage frequency refresh cycle register
        OT_FUNX = 0x18, --Output configuration register
        MODE = 0x19, --User mode selection register
        GAIN_CR = 0x1A, --Current channel gain control register
        SOFT_RESET = 0x1C, --When writing 0x5A5A5A, the user area register is reset
        USR_WRPROT = 0x1D --User write protection setting register.
                                     --After writing 0x55, the user operation register can be written;
                                     --Write other values, the user operation register area cannot be written
    },
    __newindex = function() end
})


local function Check_ConStat(HEAD,address,data0_7,data8_15,data16_23)
     local sum=HEAD + address + data0_7 + data8_15 + data16_23
     local sumAnd=bit.band(sum,0xff)
     local checksum=bit.bnot(sumAnd)--This output digit is greater than 2 bytes, and its decimal digit is -207 Hexadecimal: FFFF FFFF FFFF FF31
     local result=bit.band(checksum,0xff)--guarantee 1 byte checksum, remove the first 14 FF
    return result;
end


function BL0942_Read(ID,address)
     uart.write(ID,string.char(bl0942.READ_HEAD,address))
end
--
 function BL0942_Write(ID,address,data0_7,data8_15,data16_23)
     local checksum=Check_ConStat(bl0942.WRITE_HEAD,address,data0_7,data8_15,data16_23)
     uart.write(ID,string.char(bl0942.WRITE_HEAD,address,data0_7,data8_15,data16_23,checksum))
end

return bl0942

Before modifying the special register, 0x55 must be written into the 0X1D register.

The code implements the function of reading the full power data packet and the 0x19 register. Special attention is paid to judging the length of the data when parsing the data returned by the serial port respectively, and discarding the data packets that do not meet the parsed length to ensure the accuracy of the data.

The other two read cycles are staggered in delay time to avoid simultaneous reads.

MODE=903 is 0011 1000 0111, which is [9:8]=11, and the baud rate is adjusted to 38400bps.

Note: Alternate loop reading will cause the current to display data of more than 600 mA. I have not solved it yet. If the full-power data packet is read separately, the data can be analyzed normally and accurately. Reading special registers is generally used during the debugging phase.