Feb 2018
While building my weather station, I needed to count the output of a Hall effect device in the anemometer and in the tipping bucket rain gauge.
Everything is on the I2C bus and I could not find an I2C binary counter and didn’t want the complexity of another processor and program just to count pulses.
This board I have designed uses two 74LS590 counters in series. These 8 bit counters have a buffered output stored by an input and a clear counters input. They count on a positive going pulse*. When the first counter in the series of two rolls over at 256 it triggers the second to count one. The buffered outputs of these two chips are read by an MCP23017 GPIO expander. Only four of the count buffer outputs from the second 74LS590 are used leaving four GPIOO from the MCP23017. These are used one each for the CLR pins and the RCK (store buffer) pins, one to enable an LED so the count pulse can be seen and one left open. *The Hall effect sensor out is pulled high by a 1oK resistor and the LED count circuit. When the Hall Effect is triggered, it pulls the count low and when it inactivates again the input is again pulled high and the counter increments. On the board I designed, I included two QWIIC connectors for daisy-chaining I2C devices and a more common 4 pin .1 centers connection point. There are three address jumpers on the board bottom,
The eagle files for the board can be downloaded from http:/hiddenridge.net/download/I2C_Counter.zip
The BOM for the board can be downloaded from http:/hiddenridge.net/download/oneboard.html
The correct board files are now on OSH Park
I had my boards made by OSH park I intend on writing a post about this experience. Bottom line, I love OSH Park,
I wrote a Python object that sets up and read/writes the MCP23017 counter. Below is my the object file:
The code is available on Git Hub https://github.com/Doug-Wyman/I2C-12-bit-binary-counter
Below this code is the code I use to read my anemometer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#!/usr/bin/env python # -*- coding: utf-8 -*- # # mcpcounter.py # # Copyright 2018 Doug Wyman <doug@stretchmain> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. # # import smbus class counter(): def __init__(self,busnum, deviceaddr, **kwargs): if busnum is None: self.busnum = int(1) else: self.busnum = busnum if deviceaddr is None: self.deviceaddr = int(0x20) else: self.deviceaddr = deviceaddr chip = smbus.SMBus(int(self.busnum)) chip.write_word_data(int(self.deviceaddr), 0x00, 4095) #set the first 12 bits to inputs self.i2c = chip self.i2c.write_byte_data(int(self.deviceaddr), 19, 208) # Set the LED on, NOT reset, and enable count self.isready = 'I am ready' def getcount(self): tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting mask1 = tmp & 176 mask2 = tmp & 240 self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1)) self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask2)) return self.i2c.read_word_data(int(self.deviceaddr), 18) & 4095 def resetcount(self): tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting mask1 = tmp & 112 mask2 = tmp & 240 self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1)) self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask2)) return self.i2c.read_word_data(int(self.deviceaddr), 18) & 4095 def LEDon(self): tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting mask1 = tmp | 16 self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1)) return "Set Pin High" def LEDoff(self): tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting mask1 = tmp & 224 self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1)) return "Set Pin Low" def AUXon(self): tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting mask1 = tmp | 32 self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1)) return "Set Pin High" def AUXoff(self): tmp = self.i2c.read_byte_data(self.deviceaddr,19) # get the current LED and aux setting mask1 = tmp & 208 self.i2c.write_byte_data(int(self.deviceaddr), 19, int(mask1)) return "Set Pin Low" print("loaded device") |
Anemometer Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import mcp_i2c from time import sleep import time import datetime import sys import mysql.connector if len(sys.argv) > 1: deviceaddr = sys.argv[1] else: deviceaddr = 0x27 print (deviceaddr) WindCount = mcp_i2c.counter(1,int(deviceaddr)) WindCount.resetcount() LastCount= int(0) Last24 = [int(0)] * 24 for num in range(1,25): RegisterLong = WindCount.getcount() if LastCount <= RegisterLong: Last24.append(RegisterLong-LastCount) print(RegisterLong-LastCount) elif LastCount > RegisterLong: Last24.append((int(4096) -LastCount) + RegisterLong) print((int(4096) -LastCount) + RegisterLong) LastCount = RegisterLong Last24.pop(0) sleep(1.9) #print("INSERT INTO `WindSpeed`(`datetime`, `twosec`) VALUES ( NOW() , '" + str(Last24).strip('[]') + "')") try: cnx = mysql.connector.connect(user='Weather', password='iamweather', host='192.168.0.11', database='Weather') #query = "INSERT INTO WindSpeed (`datetime`, `twosec`) VALUES ( NOW() , '" + str(Last24).strip('[]') + "')" query = "INSERT INTO anemometer (`datetime`, `01`, `02`, `03`, `04`, `05`, `06`, `07`, `08`, `09`, `10`, `11`, `12`, `13`, `14`, `15`, `16`, `17`, `18`, `19`, `20`, `21`, `22`, `23`, `24` ) VALUES ( NOW() , " + str(Last24).strip('[]') + ")" print(query) cursor = cnx.cursor() cursor.execute(query) cnx.commit() cursor.close() cnx.close() print ("updated db WX") except Exception as e: print(e) print ("Error Updating WxDB") pass try: cnx = mysql.connector.connect(user='Weather', password='iamweather', host='192.168.0.158', database='weather') #query = "INSERT INTO WindSpeed (`datetime`, `twosec`) VALUES ( NOW() , '" + str(Last24).strip('[]') + "')" query = "INSERT INTO anemometer (`datetime`, `01`, `02`, `03`, `04`, `05`, `06`, `07`, `08`, `09`, `10`, `11`, `12`, `13`, `14`, `15`, `16`, `17`, `18`, `19`, `20`, `21`, `22`, `23`, `24` ) VALUES ( NOW() , " + str(Last24).strip('[]') + ")" print(query) cursor = cnx.cursor() cursor.execute(query) cnx.commit() cursor.close() cnx.close() print ("updated db 158") except Exception as e: print(e) print ("Error Updating 158") pass |
I have 3 boards coming from OSH hope to accumulate windspeed data while the esp32 is asleep. Wonderful that your coding in python. This is not tested but I wonder if something like:
RegisterLong=sum([2**t[0]*t[1] for t in enumerate(RegisterIn)})
Would work? Will try when I get the boards in.
Thanks for publishing on OSH!
RegisterLong=sum([2**t[0]*t[1] for t in enumerate(RegisterIn)])
Sorry for the typeO.
With RegisterIn=[1,0,0,1,0,0,0,0,0,0,0,1]
>>> RegisterLong
2057
Thank you for the line of code. I knew there had to be a python way to make a single equation. Aaah I may be superannuated but I’m still learning.
Please remember the latest board files are on http://hiddenridge.net/download/I2C_Counter.zip