Monday, July 14, 2014

On 12:10 PM by Richard St-Pierre   No comments

OVERVIEW

Have you ever needed a program to run at a given time everyday, every hour, every 15 minutes? Forgetting to water the plants? Want to collect weather information on a fixed interval? Need to collect data over time to look for correlation in slow changing events? Interested in taking time-lapse pictures of your project? Curious about trends? Ever wondered what happens to your project when you are not there?

"Cron " is a Linux time-based scheduler that allows tasks to run at a given time automatically. Typically used to automate system maintenance and administration tasks, Cron has a wide range of very useful applications.

The BeagleBone Black, with its generous GPIO (General Purpose Input/Output) connections and measurement capability is a perfect computer for collecting data. This tutorial will guide through setting up a Cron job for your BeagleBone. As a simple example, we will measure ambient light levels over an entire day.


What you will need

Instructions

There are two parts to set up 'Cron'.  First, we need to have a task (program) that we want to do (examples: measure ambient light, temperature, pressure, read sensors). Second, we need to define when we want the task(s) to run.

Note: It is important that the system clock is set accurately, as we will depend on it to schedule events.

About Scripts, Tasks, Commands


A task or job is simply a list of command(s). An example of a simple task might be:

echo "Hello it's time for Lunch" (*note)

We can combine multiple commands in a file:

#!/bin/bash
echo "Hello it's time for Lunch"

The first line is required, to identify the type of script language that is used.
To make the task file executable:

chmod a+x mytask.sh

And we can test our script:

./mytask.sh

Notes:
(*) Cron jobs run in the background so you will not see messages, unless you direct them to a file.
You should include the full path name to the files you specify in the scripts.

STEP 1

For this tutorial we will call a program that collects measurements from an ambient light sensor and sends the data sample to a file. The program will also record the time of each measurement. Later, the collected data will be plotted.

Let's create a file "adc_cron.py".

Download adc_cron.py File
and save this file as adc_cron.py (without the *.txt extension) to a working location on your BeagleBone.

Program Listing

#!/usr/bin/python
#Logic Supply Tutorial for the BeagleBone Black ARM Cortex A8
# visit http://inspire.logicsupply.com
# Author : Richard St-Pierre
# Version: 1.0  July 1, 2014  Initial version
#          1.1  July 9, 2014  File Append mode for cron (adc_cron.py)
# -------------------------------------
# This Python program is called by a cron job
# which reads and  records the analog inputs
# to a user file at fixed time interval.
# The data file can then be plotted with gnuPlot.
#
# NOTE:  Unconnected inputs will 'float'
# unless connected to ground (zero volts).
# -------------------------------------

import Adafruit_BBIO.ADC as ADC
import Adafruit_BBIO.GPIO as GPIO
import time
import datetime

#--- Define Pins ---
led_G    = "P8_19"         # in series with 330 Ohms resistor
adcPins  = ["P9_39","P9_40","P9_37","P9_38","P9_33","P9_36","P9_35"] #AIN0-AIN6

#--- Define Variables ---

myfilename = "myData.dat"  #filename to store data

#--- Setup Pins ---

ADC.setup()
GPIO.setup(led_G, GPIO.OUT)
GPIO.output(led_G, GPIO.LOW)

#--- Display Program Info ---

print '\nLogic Supply --- Data Acquisition Tutorial'
print 'visit:  inspire.logicsupply.com\n'

#--- Open DataFile ---

with open(myfilename,'a') as f:

    print 'Datalogging.... '
    GPIO.output(led_G, GPIO.HIGH)

    f.write('\n'+ datetime.datetime.now().strftime("%H:%M"))

    for i in range(len(adcPins)):
            adc  =  ADC.read_raw(adcPins[i])
            f.write(', '+ str(adc))

#--- CleanUp and Exit ---

GPIO.output(led_G, GPIO.LOW)
print ('Data file: '+ myfilename + ' appended.\n')

Program Overview

First, in this python program, we declare the libraries we are going to use. ADC for measurement, GPIO for the LED, and 'datetime' to datalog the system time.  Next we define the pins we are going to use and assign a filename to store our data. Then, we can setup the pins so they will work the way we want to use them.

Now we open our datafile so that we can append data to it.  An LED is turned On during measurements (this is purely optional).  The first column of our text datafile is populated with the system time, so that we know when this data entry was made. The data measurements are stored next; with the sampling of all seven analog input channels (AIN0-AIN6).  While we are only using AIN5 in this tutorial, your particular application may require measuring multiple channels.

The print statements are only needed during debug.Finally its time to cleanup and exit.

STEP 2

We are now ready to connect the ambient light sensor. (Be sure to turn Off power to the BeagleBone first). We create a simple voltage divider between the fixed 10K resistor (P9-34) and the variable photo resistor (P9-32). The common point of both components is connected to the BeagleBone analog input AIN5 (P9-36). Remember the maximum voltage on the AINx pins is 1.8V.




Connection Summary

P9-32 (VREF) to one side of Light Sensor
P9-34 (AGND) to one side of 10K Resistor
P9-36 (AIN5) to common point of both Light Sensor and 10K Resistor

STEP 3

Now, we'll test our sensor circuit to make sure everything is working.

We can run the program two ways:

sudo python adc_cron.py

chmod a+x adc_cron.py
./adc_cron.py 

Then we create a datafile "myData.dat" with the measured data:

cat myData.dat

Here is an example of our test data. As you can see we are collecting all seven analog inputs, although we only need one here:

09:40AM, 0.0, 0.0, 0.0, 0.0, 0.0, 1727.0, 0.0

And a second time with the sensor partially covered (dark):

09:41AM, 0.0, 0.0, 0.0, 0.0, 0.0, 906.0, 0.0

Great, we have our ambient light sensor reading on AIN5.

Un-used channels will 'float' and will not be zero unless connected to 0V (ground).

About 'Cron' Formatting

A flexible scheme to schedule the events and task is described in this format.

Five fields are followed by a command to execute. The first field defines the minutes. The second the hour. Third is day of the month. Forth is which month, and finally the day of the week.

Example:
00 12 * * * lunch

(Min 00, Hour 12, * Everyday, * Every month, *Every day of the week) run the script 'lunch'
Everyday at 12:00 run 'lunch'

Cron Format
* * * * *  command to execute
 ┬ ┬ ┬ ┬ ┬
 │ │ │ │ │
 │ │ │ │ │
 │ │ │ │ └───── day of week (0 - 6) (0 to 6 Sun to Sat)
 │ │ │ └────────── month (1 - 12)
 │ │ └─────────────── day of month (1 - 31)
 │ └──────────────────── hour (0 - 23)
 └───────────────────────── min (0 - 59)

Special CharactersMeaning
* (asterisk)Matches all values (ex: every month)
/ (slash)Increment of ranges  (ex: every 10 minutes)
- (dash)Defines a range (2013-2014)
, (Comma)Separates items in a list ("MON,FRI")
% (Percent)Changes all but \ into new line
? (Question mark)some Implementation allow ? instead of *
# (Hash)Allowed for day-of-week field (ex: second monday of month
LLast (ex:last day of month)
Win Day-of-the-Month (specifies weekday (Mon-Fri)

Special Keywords

Special KeywordMeaning
@yearlyEquivalent to 0 0 1 1 *
@dailyEquivalent to 0 0 * * * 
@hourlyEquivalent to 0 * * * *
@rebootRun at start up

More Examples

ExampleMeaning
00 09-18 * * 1-5 Every week day (except Sat,Sun) at 9, 10,11,12,1pm, 2pm, 3pm 4pm, 5pm, 6pm
*/10 * * * *Schedule task every 10 minutes
0 */4 * * *Schedule task every 4 hours, on the hour
* * * * 5Schedule task every 5th weekday
* * * * FriSchedule task every Friday
* 8-22/2 * * *Schedule task every 2 hours between 8am and 10pm
@dailyEveryday at 00:00


STEP 4

Now we are ready to automate this process! We want to use the 'crontab' utility to create the scheduled task.

To edit crontab entries:

crontab -e

We want to add the following line:

*/15 * * * * sudo python adc_cron.py

This will call the 'adc_cron.py' program every 15 minutes and record the measurement data to the file "myData.dat".

To list cron jobs (-l is lower case "L"):

crontab -l

To view the status of Cron jobs that have been executed:

/etc/init.d/cron status

STEP 5

Finally, we want to plot our measurement results. This too can be automated using Gnuplot. This tutorial has more details on using Gnuplot.

Download plotCronData.gp File
and save this file as plotCronData.gp (without the *.txt extension) to a working location on your BeagleBone.

Program Listing

# Logic Supply Tutorial
# Richard St-Pierre
# Gnuplot demo on BeagleBone Black/Debian
# Version 1.0 July 10, 2014 
reset
set yrange[0:2000]
set mytics 10
set xtics rotate by 90 offset 0,-2
set xdata time
set timefmt "%H:%M"
set format x "%H:%M"
set datafile separator ","
set title  "Logic Supply Tutorial\n inspire.logicsupply.com"
set xlabel "Time"
set ylabel " Ambient Light"
set timestamp "%B %d %Y %H:%M" top
set grid
plot 'myData.dat' using 1:7 lt 1 lw 2 title "Light Sensor1" with lines

# Let's also make a png file of our plot
set terminal png
set output "myCronPlot.png"
replot

# This will pause the display for 10 seconds to view the plot.
pause 10 "Done-Pausing..."

Program Overview

The Gnuplot script starts with a reset. We then set the range for the measurements. We then tell Gnuplot that we have commas separating our data.  Next, we add labels and titles for our graph. As a measurement record, a time stamp is desired. A grid provides easier reading. In a single command, we can now plot our measurement data and give it a data label. We plot time (column 1) against AIN5 (column 7) with the "1:7" parameter statement. Finally, we also generate a .png image file of our data plot so that we can include the graph in documents, or webpages.  This project is a simple practical example of a basic IoT (Internet Of Things) device that could be used in conjunction with any number of various applications.

To run the plotting script, we need to install Gnuplot and to be directly connected to the BeagleBone or establish a VNC session.

In the VNC (Virtual Network Connection) session, open a terminal and enter:

gnuplot plotCronData.gp

Sun Rise

Full Day


Going Further

In this tutorial we connected a single sensor as a simple demonstration. The software provided measures up to 7 sensors. Multiple additional inputs/sensors can easily be measured, recorded and plotted.

Beyond measurement and recording, the powerful ARM processor of the BeagleBone can be used to respond and control devices based on the analysis of the measurement data.

Now that we know more, we could use 'cron' to generate the plot(s) automatically (at a specific time!), email us a report, send reminders, and even order more product or supplies (based on measured consumption). Network capabilities also open up a whole new realm of applications. What will you do next?

0 comments:

Post a Comment