Raspberry Pi – Frequency pulse read 20 kHz

I was trying to find if it was possible to read a frequency generated by a anemometer with a Raspberry Pi. The information i found was there but very sparse and somewhat messy. Som said, NO!, the RPI cannot read frequencies and some said it had hard limitations. I figured the best way was to test everything out for myself and see if it would work out or not. Then i figured i try to simplify it here and hope it will help others in the same situation.

With this test i have concluded that up to 20 kHz the RPI is stable to read digital pulses.

First of i must say that i’m neither an expert in python or electronics. I studied electronics for three years back in 2002-2005. After that time i have had coding as a hobby. I worked my way trough html, css, php, mysql, after some years i started with arduino and c++ and now the last few years also raspberries and python. I have also run several Linux servers for home use.

Hardware used for this project:

  • Raspberry Pi 3 B+
  • One 100 ohm resistor
  • Uni-T UTG1005A Signal generator
  • Rigol DS1054 Z

The python code for this project is below.

import RPi.GPIO as g
from time import sleep

g.setmode(g.BCM)
g.setup(16, g.IN, pull_up_down=g.PUD_DOWN)

global input
input = 0

def freq(x):
    global input
    input += 1

g.add_event_detect(16, g.RISING, callback=freq)

while True:
    sleep(1)
    print(input)
    input = 0

Code above uses pin 16 for reading the frequency. You can change this to suit your needs, just remember to alter the code as well as the input position.

Test bench setup

In the image above the signal generator is coming from the right(black and red clamp). It shares ground with the RPI and the signal generator gover over a 100 ohm resistor.

Kicad circuit of the test bench

For my project it is relevant to test the RPI with frequencies up to 600Hz. But i’m going to test how far the RPI can read stable frequencies in this setup.

Results

I created a bit more advanced script to make the progress a bit smoother and more consistent. Also i wanted to log every reading in a database. I created a database table, with 30 empty rows.

To automate this test i added some more bits to the python script.

import mysql.connector
import RPi.GPIO as g
from time import sleep

global infreq
infreq = 0


def freq(x):
	global infreq
	infreq += 1


def db_insert(x, v, i2):
	writeDB = "UPDATE freq SET {} = {} WHERE id = {}".format(x, v, i2)
	cnx = mysql.connector.connect(user='pi', database='freq', password='password')
	cursor = cnx.cursor()
	cursor.execute(writeDB)
	cnx.commit()
	sleep(0.1)


g.setmode(g.BCM)
g.setup(16, g.IN, pull_up_down=g.PUD_DOWN)
g.add_event_detect(16, g.RISING, callback=freq)

v = [0] * 30
# x = 0
# i2 = 0
# dbid = 0

f = ["5hz", "10hz", "11hz", "20hz", "53hz", "100hz", "190hz", "253hz", "350hz",
 "500hz", "600hz", "700hz", "800hz", "900hz", "1000hz", "1500hz", "3000hz",
 "6000hz", "9000hz", "12000hz", "15000hz", "18000hz", "21000hz"]



print("      Raspberry Pi - Frequency test")
print("        Written by Stefan Bahrawy")
print("")
print("This test will read frequencies and store them in a database.")
print("Each test will work for 30 sec, then prompt for new frequency. So be patient.")
print("")
input("Hit enter to set you first frequency and start the reading.")


for x in f:
	input("Set frequency to \x1b[1;31m {} \x1b[0m, and hit enter. 
Sit back and relax for 30sec".format(x))
	infreq = 0
	for d in range(30):
		sleep(1)
		v[d] = infreq
		infreq = 0
	print("Reading done, now DB insert")
	for i in range(30):
		i2 = i + 1
		print(x, "Reads: ", v[i])
		db_insert(x, v[i], i2)
	print("\x1b[1;32m 30 readings stored in database column {} \x1b[0m".format(x))
	print("")

print("")
print("The test is complete")

Random dumps from the oscilloscope. Showing all readings.

Below is the csv convertion from the MySQL dump i did after the full test. If you are interested in the data, just download it. Let me know if you would like the sql file and i can send it to you.

Conclusion

For my use the results are good enough. Having deviations of 1Hz here and there. If you are looking for higher accuracy, you might get some with the use of a new RPI, clean install or maybe threading to separate the processes.

If you have questions dont hesitate to ask.