Tag Archives: pyfirmata

Thermistor + pyfirmata

Want to know how to use a thermistor with your arduino via pyfirmata? Look no further…

I’ve been playing with thermistors as part of a home monitoring system I’ve been building and for an upcoming sous vide project. Thermistors are cheap and can be highly accurate for a pretty wide range of temperatures. I’m using an epoxy coated and waterproofed thermistor for my sous vide project.

The Setup

You need:

  • an arduino
  • a thermistor
  • a resistor that matches your thermistor (ie: 10k ohm resistor with 10 k ohm thermistor)
  • a breadboard with jumper wires

pyfirmata thermistor

The Code

Code available for download

### THERMISTOR TEMPERATURE READINGS VIA PYFIRMATA 
### JS Kouri 2/1/2014, no rights reserved
### In this example, I am using a 4.7 kΩ resistor 
### (Digi-Key Part Number NTCLE400E3472H)
### Values for Steinhart-Hart equation calculated 
### at http://bit.ly/1nPiOLv from datasheet info

import pyfirmata
from math import log
from time import sleep

n = 0							#first port number to try ie: ttyACM0
PORT = '/dev/ttyACM' + str(n)    			# device location, yours may very. if unable to connect, try /dev/USB or check dmesg
connected = False 

def connection():
  global board
  board = pyfirmata.Arduino(PORT)
  print 'Port found, connecting...'
  it = pyfirmata.util.Iterator(board) # start iterator thread
  it.start()

# ATTEMPT TO CONNECT TO ARDUINO. ITERATE THROUGH PORT NUMBERS UNTIL CONNECTED  
while connected == False:
  try:
    print 'Trying' + PORT
    connection()
    connected = True
    print "Connection established"
  except:
    n = n+1
    PORT = '/dev/ttyACM' + str(n)
    pass

# WAIT UNTIL INPUT RECEIVED AT ANALOG PIN  
pin0 = board.get_pin('a:0:i')				# edit to reflect your setup
print 'Waiting on reading...'
while pin0.read() is None:				# ignore input until pin is active
    pass

while True:

  analog_value = pin0.read()
  #print analog_value 					# optional debug info

  # VOLTAGE DIVIDER CALCULATION
  analog_value = analog_value * 5			# we multiply by 5 (volts) to get the true voltage read at pin (ie: we get 3 v instead of 0.6. pyfirmata reports analog values in the range of 0 to 1. 
  analog_value = 4700.0 * ((5.0/analog_value) -1.0) 	# solve for resistance at thermistor. change 4700 to match your resistor used.

  #print str(analog_value) + ' this is calculated resistance in ohms at thermistor' # optional debug info

# STEINHART-HART EQUATION
  temp = (1 / (0.001308463361 + 0.0002344771590 * log(analog_value) + 0.0000001041772095 * log(analog_value)**3)) # substitute your thermistor's unique values for A, B, C. 

  # TEMP IN KELVIN
  print str(temp) + ' kelvin'

  #TEMP IN CELSIUS
  t_celsius = temp - 273.15
  print str(temp) + ' degrees celsius'

  #TEMP IN FAHRENHEIT
  t_fahrenheit = 9/5.0*temp + 32
  print str(t_fahrenheit) + ' degrees fahrenheit\n\n'  

  sleep(30) 						# wait 30 seconds between polling pin

The Explanation

The code features a few important aspects that understanding will be helpful.

Converting Pyfirmata Analog Values to Voltage

Pyfirmata reports analog values as a float of 0 to 1. We need to determine what the voltage is at the analog pin. We’re using 5 VDC so we multiply it by 5.  This will provide Va for the next portion.

The Voltage Divider

A neat little explanation of why we use voltage divider circuits with thermistors and other sensors can be found here. No need to rehash it.

In order to obtain the resistance of the thermistor, we need to calculate it based off the voltage readings from the analog pin. (Which we just adjusted). We use an equation derived from Ohm’s Law that lets us calculate the resistance in a voltage divider.

RT = R  [1 / (V / VA – 1) ]

Where RT = thermistor resistance in ohms, R = resistor resistance, V = input voltage, VA = voltage reading from analog pin (Read more at Wikipedia Voltage Divider)

 Armed with the resistance at the thermistor, we can finally calculate the temperature.

Steinhart-Hart Equation

There are  a couple ways of calculating this, I chose the Steinhart-Hart equation, but you can also use the simpler β equation. (See Wikipedia)

Where R = thermistor resistance. (Written as RT in last section)

It is very important to have your datasheet in order to accurately calculate the values needed for this equation. If you don’t have the datasheet, you can determine your own values by obtaining resistance in ohms at three known temperatures.

thermistor_datasheet
my thermistor’s data sheet and the values I used in the calculator

 

Once you get your  resistance values for three known temperatures from your datasheet or experimental data, plug them into a Steinhart-Hart calculator and build your equation.

Replace my values in the code above with yours. Be sure to format the coefficients properly. The calculator I linked to above gives coefficients in scientific notation. Convert scientific notation to the long form decimal notation. (n-1 preceding decimal places for E to the n power)

Now run it and get your temperature!

 Sky’s The Limit

And there you have it. From here you can easily save your values in a text file or a database, build cool charts with matplotlib (if you don’t pull your hair out first trying to get it to work), or do something more dynamic like create feedback loops and control things based on temperature.

Overengineered Morse Code with the Arduino

As a first foray into python, arduino, and pyfirmata (after lighting a single LED), I wrote this small python script for converting text into morse code. I first ran it with a single LED on a breadboard, but it was much more fun to throw in a piezo buzzer and get the unmistakeable morse beeps.

See the code and schematics below. As someone with less than a month of on and off again python study, don’t expect anything too ‘pythonic’ and pretty. It works though!

Script requires the pyfirmata module. Be sure to adjust the pin number and port/device location of the arduino in the script.

### Arduino / Raspi Morse Code Generator
### Enter a word, and get morse code translation in console output & LED lights / beeps



import pyfirmata


### MORSE CODE ALPHABET ###
morse = {'a':['.','-'],
	 'b':['-','.','.','.'],
	 'c':['-','.','-','.'],
	 'd':['-','.','.'],
	 'e':['.'],
	 'f':['.','.','-','.'],
	 'g':['-','-','.'],
	 'h':['.','.','.','.'],
	 'i':['.','.'],
	 'j':['.','-','-','-'],
	 'k':['-','.','-'],
	 'l':['.','-','.','.'],
	 'm':['-','-'],
	 'n':['-','.'],
	 'o':['-','-','-'],
	 'p':['.','-','-','.'],
	 'q':['-','-','.','-'],
	 'r':['.','-','.'],
	 's':['.','-','-','-'],
	 't':['-','.','-'],
	 'u':['.','-','.','.'],
	 'v':['-','-'],
	 'w':['-','.'],
	 'x':['-','-','-'],
	 'y':['.','-','-','.'],
	 'z':['-','-','.','-'],
	 ' ':' '}


### CONNECT TO ARDUINO ###
port = '/dev/ttyACM0'
board = pyfirmata.Arduino(port)

### SET PIN NUMBER ###
pin = 7 

def program():

### DELAY FACTORS ###
  delay = 0.15						# Length of time LED between inter elemental lighting
  delay_factor = 1					# Speed up or slow down entire program by set percentage Default: 1
  delay_intraletter = delay * delay_factor * 3		# Length of time between letters 
  delay_interword = delay * delay_factor * 7		# Length of time between words
  delay_dit = delay * delay_factor			# Length of illumination for dot/dit
  delay_dah = delay_intraletter	 


  user_list = [] 									# blank list
  user_input = raw_input("Enter your word to convert to morse code: ").lower()		# Take user input, convert to lowercase
  for x in user_input:
    user_list.extend(morse.get(x))
  print user_list
  print '\n Creating morse message now...'
  user_list = ''.join(user_list)
 # print 'DEBUG: joined user list'
 # print user_list
 
  for l in user_list:
    
    if l == '.':
      board.pass_time(delay_intraletter)
      board.digital[pin].write(1)
      print 'TRANSMITTING: .'
      board.pass_time(delay_dit)
      board.digital[pin].write(0)
    
    elif l == '-':
      board.pass_time(delay_intraletter)
      board.digital[pin].write(1)
      print 'TRANSMITTING: -'
      board.pass_time(delay_dah)
      board.digital[pin].write(0)
      
    elif l == ' ':
      board.pass_time(delay_interword)
      print 'NEW WORD'	

    else:
	pass
      
   
   
program()
  

The circuit is even simpler than the script. It amounts to nothing more than a piezo buzzer (unsure of the specs of mine), LED, and resistor in series.

Easy enough, right?
Easy enough, right?

So what had originally sprung up as an idea to play around with the pyfirmata syntax turned into a drive to learn morse code, which quickly faded into disinterest by the time I had finished transcoding the alphabet. I have since made an updated version that includes numbers and communicates between two computers on a network via the python SOCKS module. I was considering adding a reverse translator as well that translates user input (via pushbutton) morse into letters. I think I have a few other projects in mind that will be of more immediate practical use.

Download the latest source files for this project here

Morse key adopted from https://en.wikipedia.org/wiki/Morse_code.