Foxtrot: Programy pro ČOV

Program pro řídící jednotku Foxtrot a čistírnu odpadních vod Aquatec AT-6. Nabízí 10 programů, dle zatížení domácnosti. Dá se později napojit na vodoměr (počitadlo) a podle toho měnit program.

TYPE
  T_COVProgram :STRUCT
    runs: ARRAY[0..23] OF usint;
  END_STRUCT
END_TYPE
VAR_GLOBAL
  COV_Programs: ARRAY[1..10] OF T_COVProgram := [
  // cas - hodina rozdelena na 12 useku po 5min.
  // hodnoty: 1 -> 1 min bezi, 5-1=4 stoji
//            0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// 1 - 5.6h celkem, 4 min stoji, 1 min bezi
    (runs := [5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
// 2 - 8.8h celkem, 4 min stoji, 1 min bezi
    (runs := [5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5]),
// 3 - 10.4h celkem, 4 min stoji, 1 min bezi
    (runs := [5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1]),
// 4 - 12h celkem, 4 min stoji, 1 min bezi
    (runs := [5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 5, 1, 1, 1, 1, 1, 5, 5]),
// 5 - 15h celkem, 3 min stoji, 2 min bezi
    (runs := [5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 2, 5, 5]),
// 6 - 18h celkem, 2 min stoji, 3 min bezi
    (runs := [5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 5, 5]),
// 7 - 20.4h celkem, 2 min stoji, 3 min bezi
    (runs := [5, 5, 5, 5, 5, 5, 3, 3, 3, 5, 5, 5, 3, 3, 3, 5, 5, 5, 3, 3, 3, 5, 5, 5]),
// 8 - 21.6h celkem, 2 min stoji, 3 min bezi
    (runs := [5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5]),
// 9 - 22.8h celkem, 2 min stoji, 3 min bezi
    (runs := [5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5]),
// 10 - 24h celkem, 24h bezi
    (runs := [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5])
   ];
END_VAR
VAR_GLOBAL RETAIN
  COV_PROGRAM : usint := 0;  
END_VAR

FUNCTION_BLOCK fbCistickaProgram
  VAR_INPUT
    prog_num: usint;
  END_VAR
  VAR_OUTPUT
    output: BOOL;
  END_VAR
  VAR_IN_OUT
  END_VAR
  VAR
    ton_stop: ton;
    ton_run: ton;
    light: fb_iLight;
    curr_time: time;
    hour: usint;
    covprg : T_COVProgram;
    mins : usint;
  END_VAR

curr_time := GetTime();
hour := hour_of_time(in := curr_time);
covprg := COV_Programs[prog_num];
mins := covprg.runs[hour];

ton_stop( IN := not ton_run.q, pt := encodeTime(M := 5-mins));
ton_run( IN := ton_stop.q, pt := encodeTime(M:= mins));

light( lightOn := ton_stop.q, lightOff := ton_run.q, name:= 'Cisticka', out => output );
END_FUNCTION_BLOCK
PROGRAM prgJson
  VAR
    cisticka : fbCistickaProgram;
  END_VAR

if COV_PROGRAM = 0 then
  COV_PROGRAM := 1;
end_if;

cisticka( prog_num := COV_PROGRAM, output => RO04_COV );
END_PROGRAM

Jsou tam ještě nějaké záseky, např. že pokud je cyklus plný (5 minut) a následuje ten samý (bez pauzy), bylo by fajn vynechat úplně vypínání výstupu, popř. zkrátit cyklus o párset ms. Dále pak přidat reset v případě změny programu atd. Každopádně to ale zatím funguje k mé spokojenosti.

STM32F4Discovery + eLua + OSX

I fixed few bugs when compiling elua from git on osx – clone my branch clone official repo here.

$ ./build_elua.lua board=stm32f4discovery

create .bin file

$ arm-none-eabi-objcopy -O binary elua_lua_stm32f4discovery.elf elua_lua_stm32f4discovery.bin

create openocd config file for stm32f4 board:

$ cat ~/stm32f4discovery.cfg
# stm32f4discover board
source [find interface/stlink-v2-1.cfg]
transport select hla_swd
source [find target/stm32f4x.cfg]
reset_config srst_only

and upload to the board:

$ openocd -f ~/stm32f4discovery.cfg \
   -c "init" \   
   -c "reset halt" \
   -c "sleep 100" \
   -c "wait_halt 2" 
   -c "echo \"--- Writing elua_lua_stm32f4discovery.bin\"" \
   -c "flash write_image erase elua_lua_stm32f4discovery.bin 0x08000000" \
   -c "sleep 100" \
   -c "echo \"--- Verifying\"" \
   -c "verify_image elua_lua_stm32f4discovery.bin 0x08000000" \
   -c "sleep 100" \
   -c "echo \"--- Done\"" \
   -c "resume" \
   -c "shutdown"

Open On-Chip Debugger 0.9.0 (2015-11-16-01:48)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 2000 kHz
adapter_nsrst_delay: 100
none separate
srst_only separate srst_nogate srst_open_drain connect_deassert_srst
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : clock speed 1800 kHz
Info : STLINK v2 JTAG v25 API v2 SWIM v14 VID 0x0483 PID 0x374B
Info : using stlink api v2
Info : Target voltage: 2.884520
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080063f0 msp: 0x20000c78
--- Writing elua_lua_stm32f4discovery.bin
auto erase enabled
Info : device id = 0x10076413
Info : flash size = 1024kbytes
wrote 262144 bytes from file elua_lua_stm32f4discovery.bin in 7.783807s (32.889 KiB/s)
--- Verifying
target state: halted
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000002e msp: 0x20000c78
verified 220776 bytes in 2.229936s (96.685 KiB/s)
--- Done
shutdown command invoked

Now you can connect to the board using /dev/tty.usbmodem621, 115200/8/n/1. You should get this prompt:

eLua#
eLua# help
Shell commands:
  help   - shell help
  lua    - start a Lua session
  ls     - lists files and directories
  dir    - lists files and directories
  cat    - list the contents of a file
  type   - list the contents of a file
  recv   - receive files via XMODEM
  cp     - copy files
  mv     - move/rename files
  rm     - remove files
  ver    - show version information
  mkdir  - create directories
  exit   - exit the shell
For more information use 'help <command>'.
eLua# lua
Press CTRL+Z to exit Lua
Lua 5.1.4  Copyright (C) 1994-2011 Lua.org, PUC-Rio
> print(pd.board() .. "/" .. pd.platform() .. "/" .. pd.cpu())
STM32F4DISCOVERY/STM32F4/STM32F407VG

enjoy :)

nodemcu + el capitan

To flash

git clone https://github.com/themadinventor/esptool.git 
cd esptool
sudo python ./setup.py install
  • upgrade firmware
$ python ./esptool.py --port=/dev/cu.wchusbserial620  write_flash  -fm=dio -fs=32m 0x00000 /tmp/nodemcu_integer_0.9.6-dev_20150704.bin

Connecting...
Erasing flash...
Took 3.92s to erase flash block
Wrote 450560 bytes at 0x00000000 in 54.1 seconds (66.6 kbit/s)...

Leaving...

MCP7940 – RTC with Pi

As I’m building my own IQ house control system, I need to have RTC in my system. So started playing with MCP7940N and i2c interface. I’m using Raspberry Pi for my experiments with i2c/SPI.

Construction is pretty simple, just use MCP7840N Datasheet.

mcp7940n-schema

 

Then you can start checking with Pi. In my case, I’m using RevB, so my bus has number 1 and RTC got 0x6f address.

root@pi:~# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 6f
70: -- -- -- -- -- -- -- --

what next? Check address 0x00, if the onboard oscilator is running

root@pi:~# i2cget -y 1 0x6f 0x00 b
0x00

0x00 means NO, it’s NOT running. So, turn it on

root@pi:~# i2cset -y1 1 0x6f 0x00 0x80

and check few times address 0x00

root@pi:~# i2cget -y 1 0x6f 0x00 b
0x87
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x88
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x89
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x90
root@pi:~# i2cget -y 1 0x6f 0x00 b
0x91

Increments! Great. That means – our oscilator is working = our clock is working too. Next step is to set current time and date. But wait. How are values stored and read/written? RTC uses BCD encoding for values, that means, eg. number 94 is stored as 9 and 4, both in 4 bits = 9 is stored as 1001 and 4 as 0100, in hexadecimal 0x94. Easy? Eg. day is using 6 bits, upper two for 0123 values, bottom bits for 0-9, so 31th will be stored as 0x31. For more details please read the PDF – RTCC Memory map. So back to setting the date & time:

# 2nd Feb 2014
root@pi:~# i2cset -y 1 0x6f 0x06 0x14
root@pi:~# i2cset -y 1 0x6f 0x05 0x02
root@pi:~# i2cset -y 1 0x6f 0x04 0x19
# 00:02:00
root@pi:~# i2cset -y 1 0x6f 0x02 0x00
root@pi:~# i2cset -y 1 0x6f 0x01 0x02
root@pi:~# i2cset -y 1 0x6f 0x01 0x80

Fine. But if we’re setting ’00’ as seconds – address 0x00 – why value 0x80? 7th bit = ST – onboard oscilator enabled.

I’ve written simple Python code to read from RTC and print out the value:

from time import sleep
import smbus
import time
import signal
import sys

bus = smbus.SMBus(1)
RTC_ADDR = 0x6f

ADDR_SEC = 0x00
ADDR_MIN = 0x01
ADDR_HOUR = 0x02

def signal_handler(signal, frame):
  sys.exit(0)

def bcd2bin(x):
  return (((x) & 0x0f) + ((x) >> 4) * 10)

if __name__ == "__main__":
  signal.signal(signal.SIGINT, signal_handler)
  while True:
    sec = bcd2bin(bus.read_byte_data(RTC_ADDR, ADDR_SEC) & 0x7f)
    min = bcd2bin(bus.read_byte_data(RTC_ADDR, ADDR_MIN) & 0x7f)
    hour = bcd2bin(bus.read_byte_data(RTC_ADDR, ADDR_HOUR) & 0x3f)
    print "%02d:%02d:%02d" % (hour, min, sec)
    sleep(0.9) # nearly 1 sec

Just run by

root@pi:~# python rtc.py
00:35:41
00:35:42
00:35:43
00:35:44
00:35:45
00:35:46

Voila! :) RTC is up and running. I’d like to check tomorrow (resp. today) morning, if everything is still working correctly, and can create next module for my IQ house control system :)