I2C 12 bit binary counter

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

Published by

Doug Wyman

The first computer I used was an 1962 IBM 1401 and the project was statistical information at JSPC Okinawa (NSA). Then as a civilian I engaged in Telecommunications and Video consulting thru 1974. I was asked to join the WSP Electronic Services Telecommunications and Computer engineering section and stayed till 2000. Then I was asket to work on the WSDOT CVISN project and did till till 2005 then back into retirement. Then WSCTC asked me to act as a consultant to CVISN and I did till 2011. I retired for the third time am learning Debian, Python, PHP and others for the first time. Superannuated but still learning

4 thoughts on “I2C 12 bit binary counter”

  1. 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!

  2. 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

    1. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *