Lichtschranke mit dem Raspberry in C
Die Auslösung der Lichtschranke wird über einen Interrupt erkannt. WiringPi bietet eine einfache Lösung hierfür.
Für eine Zeitmessung werden hier zwei Lichtschranken eingesetzt.
Installation wiringPI
cd
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
Programm
Für zeitkritische Anwendungen möchte ich mich nicht auf Python verlassen. Daher wurde das Programm in C erstellt.
/*
* lichtschranke.c:
* measure time with two lightbarriers
* 2014-01-17 by Thomas Hoeser
*
* git clone git://git.drogon.net/wiringPi
* cd wiringPi
* ./build
* gcc -lwiringPi -o lichtschranke lichtschranke.c
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <errno.h>
#define PIN_IN_1 3 // GPIO 22 - header PIN 15
#define PIN_IN_2 5 // GPIO 24 - header PIN 18
#define MYDEBUG // rename to ignore debug code in final build
struct timeval t1_light ; // Time of first light barrier
struct timeval t2_light ; // Time of second light barrier
static volatile int globalCounter = 0;
typedef enum { false, true } bool;
static volatile bool globalActive = false; // set to 1 if 1st light barrier is passed
// i.e. measuring is active and signal for 1st ligth barrier should be ignored
static volatile bool globalEcho = false;
// ----------------------------------------------------------------------------------
void showElapsedTime(void) {
static int t_delay,seconds,useconds;
seconds = t2_light.tv_sec - t1_light.tv_sec;
useconds = t2_light.tv_usec - t1_light.tv_usec;
if(useconds < 0) {
useconds += 1000000;
seconds--;
}
printf("start #%d -> %d sec %d msec\n",globalCounter,t1_light.tv_sec,t1_light.tv_usec);
printf("end #%d -> %d sec %d msec\n",globalCounter,t2_light.tv_sec,t2_light.tv_usec);
printf("Elapsed Time #%d -> var start/end: %d sec %d msec\n\n",globalCounter,seconds,useconds/1000);
} // end showElapsedTime()
// ----------------------------------------------------------------------------------
void myInterrupt1(void) {
if(globalActive==false){ // check if time measurement is already active
globalActive = true;
if(globalEcho==true){
printf ("STD Light Barrier 1 - Global Counter = %d\n",++globalCounter);
}
gettimeofday(&t1_light, NULL); // get current time and save in variable t1_light
}
} // end myInterrupt1()
// ----------------------------------------------------------------------------------
void myInterrupt2(void) {
if(globalEcho==true){printf ("STD Light Barrier 2\n");}
gettimeofday(&t2_light, NULL); // get current time and save in variable t2_light
showElapsedTime();
globalActive = false; // reset status for next measurement
} // end myInterrupt2()
// ----------------------------------------------------------------------------------
int main()
{
globalCounter = 0; // set global counter
globalEcho = true; // enable printf in interrupt function
globalActive = false; // measurement is not active
printf ("init - Global Counter = %d\n",globalCounter);
// test code - no interrupt
#ifdef MYDEBUG
myInterrupt1();
delay (123) ; // wait for given time [milliseconds]
myInterrupt2();
myInterrupt1();
delay (123) ; // wait for given time [milliseconds]
myInterrupt1();
delay (200) ; // wait for given time [milliseconds]
myInterrupt2();
#endif
// end test code - no interrupt
// wiring pi - interrupt
globalEcho = false; // do not waste time with printf; this may distort measurement
wiringPiSetup();
wiringPiISR(PIN_IN_1, INT_EDGE_RISING, &myInterrupt1);
wiringPiISR(PIN_IN_2, INT_EDGE_RISING, &myInterrupt2);
// Waste time but not CPU
for (;;) {
sleep(1000);
}
return 0;
} // end main()
Programm compilieren + starten
gcc -I. -o lichtschranke lichtschranke.c -lwiringPi
sudo ./lichtschranke
Hardware
Einen Schaltplan kann man hier sehen: https://hoeser-medien.de/?p=1184