Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Wednesday, March 30, 2016

Measuring water temperature in food-safe applications with Raspberry PI + PT100 sensor + Tinkerforge PTC Bricklet

I was looking for a temperature sensor (thermometer) that can be used with a Raspberry PI for measuring water temperature in food-safe (lebensmittelecht) applications.

The sensor should satisfy the following requirements:
  • food-safe
  • waterproof
  • heat resistant until at least 100°C
Since I couldn't find any out-of-the-box solution for the Raspberry PI, I decided to look for a separate temperature sensor and then trying to connect it with the Raspberry PI. Therefore, I found the PT100 temperature sensor, which pretty much satisfies all the given requirements.

The problem is, that a PT100 sensor cannot just be connected with a Raspberry PI, because you need an analog-digital converter. Lucky as I am, the company Tinkerforge offers some very nice modules to improve this situation. To connect a PT100 temperature sensor, you can use the Tinkerforge PTC Bricklet which gives you the current temperatur in Celsius as an integer number. Its getting even better: Tinkerforge offers an easy to use API for the "most popular" programming languages - including Python.

To connect the Tinkerforge PTC Bricklet with the Raspberry PI, you also need the Tinkerforge Master Brick, which is capable of connecting up to four Bricklets and has a mini USB connector to connect it with a computer.

The first thing to do, is to install brickd. When brickd is up and running, I recommend to change the following two lines in /etc/brickd.conf:
  •  listen.address = 127.0.0.1
  •  authentication.secret = topsecret
First, only allow local connections and second, specify a password for the authentication (I was having problems, when I disabled authentication). After brickd is configured properly, you need to find out the device identifiers of your Tinkerforge bricks, in order to use them through the API. Tinkerforge already provides a sample Python script that will list all connected devices. Because we previously configured authentication, the sample Python script needs to be modified, so that it will authenticate against brickd. In order to do so, add the following method call after the line where the call to the connect method takes place:

ipcon.authenticate('topsecret')

Replace 'topsecret' with your authentication password. Before you can make use of the Tinkerforge API, you have to install the bindings for the language that you want to use. In our case, the easiest way to do that, is to download the ZIP file with the Python bindings and copy the directory source/tinkerforge to your prefered location on your harddisc. To be able to import the bindings from a Python script, just copy the Python script to the same location where you copied the tinkerforge directory. After this is all done, you can run the script and it will output all connected devices and their corresponding identifiers.

Sunday, April 13, 2014

Dynamic and Static Typing

It happened to me more than once, that I heard people talking about something referred to as "scripting languages" and the fact that those kind of languages have no types. In this post, I want to clarify this subject in more detail. The term "scripting language" doesn't really exist in Computer Science. Therefore, two different type systems for programming languages do exist: compiled (static) and interpreted (dynamic). With static typed languages, the type checking takes place during compilation, whereas dynamic typed languages do the type checking at runtime, by the interpreter that executes the program. Popular representatives for statically typed (and compiled) languages are for example C++ and Java. Python, Perl and Ruby are languages which are dynamically typed and executed by an Interpreter.

But how is a software developer confronted with dynamic and static typing?

Example No.1 (Scala):
scala> var i = 42
i: Int = 42

Scala is a statically typed programming language, but sometimes it might look like its dynamically typed, because it allows the developer to write less boilerplate code. After assigning the integer value 42 to the variable i, the Scala compiler is able to recognize that i is of type Int, which is done through type inference. The compiler "guesses" the type of the variable by determining the type of the expression on the right hand side of the assignment.

Lets look what happens, if we try to assign a string to i:

scala> i = "Hello World!"
<console>:8: error: type mismatch;
 found   : String("Hello World!")
 required: Int
       i = "Hello World!"


Since the variable i is of type Int, we cannot assign it any value that is different from the type of integer -  due to the fact of static typing. A special case is Polymorphism, where a "super-type", can hold values (references) of all "sub-types".

Example No.2 (Python):
>>> i = 42
>>> type(i)
 <type 'int'>

In the second example, I did the same assignment as before, but using a dynamically typed programming language - in this case: Python. To invalidate the argument, that (scripting) languages like Python have no types, look at line three. Every variable in Python has a type, that can be determined at any given point in time during execution by using the type function.

Lets look what happens, if we try to assign a non-integer value to i:

>>> i = "Hello World!"
>>> type(i)
<type 'str'>


As we can see, the type of variable i has changed from integer to string. That is due to the fact, that Python is a dynamically typed programming language, where the type of a variable can change over time.

Both, dynamic and static typed programming languages have pros and cons. Dynamic typed languages are a good choice for rapid prototyping, because sometimes types stay in the way, when developers want to be creative and think about a solution for a problem. On the other side, since the absence of a compiler, the developer has to make sure that for example, a method that awaits an integer as argument, is not called given a string - which would lead most likely to a runtime exception, depending on the methods implementation.

Although, dynamically typed languages easy rapid prototyping, they are often slower than compiled languages. Furthermore, refactoring is more difficult when using dynamic typed languages, because syntax errors (wrong (text-)replacements) are not discovered by a compiler, but have to be found by self-written unit tests. Therefore, a really high test coverage of the whole source code is necessary.

References:
DynamicTyping
Type System
Type Systems for Programming Languages

Wednesday, March 26, 2014

Execute Programs and Handle their Output with Python

One nice feature of Perl is how easy it is to execute external programs. Therefore, one can use the built-in qx() function ("quote execute"). For example:

my $output = qx(cat /var/log/messages | grep fail);

After the above line has been executed, the variable output holds all system messages that contain the substring "fail". To achieve an equivalent solution with Python prior to version 2.6, the popen() function of the os module could be used:

import os
f = os.popen('cat /var/log/messages | grep fail', 'r')
output = f.readlines()
f.close()


Or shorter:

output = os.popen('cat /var/log/messages | grep fail').readlines()

Since the above is marked as deprecated starting with Python 2.6, a less intuitionally solution has to be implemented by using the subprocess module.

import subprocess
cmd = 'cat /var/log/messages | grep fail'
f = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
output = f.readlines()
f.close()


Or shorter:

output = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout.readlines()

Putting it all together, here's the qx() function written as a one-liner:

def qx(cmd):
    return subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout.readlines()

IMPORTANT: Make sure that you don't execute any given string, but only those who you trust!


References:
http://docs.python.org/2/library/subprocess.html#subprocess-replacements