delayMicrosecondsHard re-written - again. Added a serialRead example program, and added in the okLed to the examples too. Updated/checked some of the GPIO/PWM code. Added in some experimental servo and tone generating code and and example or 2. Tweaks to the gpio command to correctly load the I2C modules too.pull/6/head
parent
183c5a6b5c
commit
25e4ec570b
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* okLed:
|
||||
* Make the OK LED on the Pi Pulsate...
|
||||
* Copyright (c) 2012 gordon Henderson, but please Share and Enjoy!
|
||||
*
|
||||
* Originally posted to the Raspberry Pi forums:
|
||||
* http://www.raspberrypi.org/phpBB3/viewtopic.php?p=162581#p162581
|
||||
*
|
||||
* Compile this and store it somewhere, then kick it off at boot time
|
||||
* e.g. by putting it in /etc/rc.local and running it in the
|
||||
* background &
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <wiringPi.h>
|
||||
#include <softPwm.h>
|
||||
|
||||
#define OK_LED 16
|
||||
|
||||
int main ()
|
||||
{
|
||||
int fd, i ;
|
||||
|
||||
if ((fd = open ("/sys/class/leds/led0/trigger", O_RDWR)) < 0)
|
||||
{
|
||||
fprintf (stderr, "Unable to change LED trigger: %s\n", strerror (errno)) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
write (fd, "none\n", 5) ;
|
||||
close (fd) ;
|
||||
|
||||
if (wiringPiSetupGpio () < 0)
|
||||
{
|
||||
fprintf (stderr, "Unable to setup GPIO: %s\n", strerror (errno)) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
softPwmCreate (OK_LED, 0, 100) ;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (i = 0 ; i <= 100 ; ++i)
|
||||
{
|
||||
softPwmWrite (OK_LED, i) ;
|
||||
delay (10) ;
|
||||
}
|
||||
delay (50) ;
|
||||
|
||||
for (i = 100 ; i >= 0 ; --i)
|
||||
{
|
||||
softPwmWrite (OK_LED, i) ;
|
||||
delay (10) ;
|
||||
}
|
||||
delay (10) ;
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
|
||||
/*
|
||||
* serialRead.c:
|
||||
* Example program to read bytes from the Serial line
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <wiringSerial.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
int fd ;
|
||||
|
||||
if ((fd = serialOpen ("/dev/ttyAMA0", 115200)) < 0)
|
||||
{
|
||||
fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
// Loop, getting and printing characters
|
||||
|
||||
for (;;)
|
||||
{
|
||||
putchar (serialGetchar (fd)) ;
|
||||
fflush (stdout) ;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <wiringPi.h>
|
||||
#include <softServo.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
if (wiringPiSetup () == -1)
|
||||
{
|
||||
fprintf (stdout, "oops: %s\n", strerror (errno)) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
softServoSetup (0, 1, 2, 3, 4, 5, 6, 7) ;
|
||||
|
||||
softServoWrite (0, 0) ;
|
||||
/*
|
||||
softServoWrite (1, 1000) ;
|
||||
softServoWrite (2, 1100) ;
|
||||
softServoWrite (3, 1200) ;
|
||||
softServoWrite (4, 1300) ;
|
||||
softServoWrite (5, 1400) ;
|
||||
softServoWrite (6, 1500) ;
|
||||
softServoWrite (7, 2200) ;
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
delay (10) ;
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <wiringPi.h>
|
||||
#include <softTone.h>
|
||||
|
||||
#define RANGE 100
|
||||
#define NUM_LEDS 12
|
||||
|
||||
int scale [8] = { 262, 294, 330, 349, 392, 440, 494, 525 } ;
|
||||
|
||||
int main ()
|
||||
{
|
||||
int i, j ;
|
||||
char buf [80] ;
|
||||
|
||||
if (wiringPiSetup () == -1)
|
||||
{
|
||||
fprintf (stdout, "oops: %s\n", strerror (errno)) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
softToneCreate (3) ;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (i = 0 ; i < 8 ; ++i)
|
||||
{
|
||||
printf ("%3d\n", i) ;
|
||||
softToneWrite (3, scale [i]) ;
|
||||
delay (500) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* softServo.c:
|
||||
* Provide N channels of software driven PWM suitable for RC
|
||||
* servo motors.
|
||||
* Copyright (c) 2012 Gordon Henderson
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||||
*
|
||||
* wiringPi is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* wiringPi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with wiringPi.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
//#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "wiringPi.h"
|
||||
#include "softServo.h"
|
||||
|
||||
// RC Servo motors are a bit of an oddity - designed in the days when
|
||||
// radio control was experimental and people were tryin to make
|
||||
// things as simple as possible as it was all very expensive...
|
||||
//
|
||||
// So... To drive an RC Servo motor, you need to send it a modified PWM
|
||||
// signal - it needs anything from 1ms to 2ms - with 1ms meaning
|
||||
// to move the server fully left, and 2ms meaning to move it fully
|
||||
// right. Then you need a long gap before sending the next pulse.
|
||||
// The reason for this is that you send a multiplexed stream of these
|
||||
// pulses up the radio signal into the reciever which de-multiplexes
|
||||
// them into the signals for each individual servo. Typically there
|
||||
// might be 8 channels, so you need at least 8 "slots" of 2mS pulses
|
||||
// meaning the entire frame must fit into a 16mS slot - which would
|
||||
// then be repeated...
|
||||
//
|
||||
// In practice we have a total slot width of about 20mS - so we're sending 50
|
||||
// updates per second to each servo.
|
||||
//
|
||||
// In this code, we don't need to be too fussy about the gap as we're not doing
|
||||
// the multipexing, but it does need to be at least 10mS, and preferably 16
|
||||
// from what I've been able to determine.
|
||||
|
||||
|
||||
#define MAX_SERVOS 8
|
||||
|
||||
static int pinMap [MAX_SERVOS] ; // Keep track of our pins
|
||||
static int pulseWidth [MAX_SERVOS] ; // microseconds
|
||||
|
||||
|
||||
/*
|
||||
* softServoThread:
|
||||
* Thread to do the actual Servo PWM output
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
static PI_THREAD (softServoThread)
|
||||
{
|
||||
register int i, j, k, m, tmp ;
|
||||
int lastDelay, pin, servo ;
|
||||
|
||||
int myDelays [MAX_SERVOS] ;
|
||||
int myPins [MAX_SERVOS] ;
|
||||
|
||||
struct timeval tNow, tStart, tPeriod, tGap, tTotal ;
|
||||
struct timespec tNs ;
|
||||
|
||||
tTotal.tv_sec = 0 ;
|
||||
tTotal.tv_usec = 8000 ;
|
||||
|
||||
piHiPri (50) ;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
gettimeofday (&tStart, NULL) ;
|
||||
|
||||
memcpy (myDelays, pulseWidth, sizeof (myDelays)) ;
|
||||
memcpy (myPins, pinMap, sizeof (myPins)) ;
|
||||
|
||||
// Sort the delays (& pins), shortest first
|
||||
|
||||
for (m = MAX_SERVOS / 2 ; m > 0 ; m /= 2 )
|
||||
for (j = m ; j < MAX_SERVOS ; ++j)
|
||||
for (i = j - m ; i >= 0 ; i -= m)
|
||||
{
|
||||
k = i + m ;
|
||||
if (myDelays [k] >= myDelays [i])
|
||||
break ;
|
||||
else // Swap
|
||||
{
|
||||
tmp = myDelays [i] ; myDelays [i] = myDelays [k] ; myDelays [k] = tmp ;
|
||||
tmp = myPins [i] ; myPins [i] = myPins [k] ; myPins [k] = tmp ;
|
||||
}
|
||||
}
|
||||
|
||||
// All on
|
||||
|
||||
lastDelay = 0 ;
|
||||
for (servo = 0 ; servo < MAX_SERVOS ; ++servo)
|
||||
{
|
||||
if ((pin = myPins [servo]) == -1)
|
||||
continue ;
|
||||
|
||||
digitalWrite (pin, HIGH) ;
|
||||
myDelays [servo] = myDelays [servo] - lastDelay ;
|
||||
lastDelay += myDelays [servo] ;
|
||||
}
|
||||
|
||||
// Now loop, turning them all off as required
|
||||
|
||||
for (servo = 0 ; servo < MAX_SERVOS ; ++servo)
|
||||
{
|
||||
if ((pin = myPins [servo]) == -1)
|
||||
continue ;
|
||||
|
||||
delayMicroseconds (myDelays [servo]) ;
|
||||
digitalWrite (pin, LOW) ;
|
||||
}
|
||||
|
||||
// Wait until the end of an 8mS time-slot
|
||||
|
||||
gettimeofday (&tNow, NULL) ;
|
||||
timersub (&tNow, &tStart, &tPeriod) ;
|
||||
timersub (&tTotal, &tPeriod, &tGap) ;
|
||||
tNs.tv_sec = tGap.tv_sec ;
|
||||
tNs.tv_nsec = tGap.tv_usec * 1000 ;
|
||||
nanosleep (&tNs, NULL) ;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* softServoWrite:
|
||||
* Write a Servo value to the given pin
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
void softServoWrite (int servoPin, int value)
|
||||
{
|
||||
int servo ;
|
||||
|
||||
servoPin &= 63 ;
|
||||
|
||||
/**/ if (value < -250)
|
||||
value = -250 ;
|
||||
else if (value > 1250)
|
||||
value = 1250 ;
|
||||
|
||||
for (servo = 0 ; servo < MAX_SERVOS ; ++servo)
|
||||
if (pinMap [servo] == servoPin)
|
||||
pulseWidth [servo] = value + 1000 ; // uS
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* softServoSetup:
|
||||
* Setup the software servo system
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
int softServoSetup (int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7)
|
||||
{
|
||||
int servo ;
|
||||
|
||||
if (p0 != -1) { pinMode (p0, OUTPUT) ; digitalWrite (p0, LOW) ; }
|
||||
if (p1 != -1) { pinMode (p1, OUTPUT) ; digitalWrite (p1, LOW) ; }
|
||||
if (p2 != -1) { pinMode (p2, OUTPUT) ; digitalWrite (p2, LOW) ; }
|
||||
if (p3 != -1) { pinMode (p3, OUTPUT) ; digitalWrite (p3, LOW) ; }
|
||||
if (p4 != -1) { pinMode (p4, OUTPUT) ; digitalWrite (p4, LOW) ; }
|
||||
if (p5 != -1) { pinMode (p5, OUTPUT) ; digitalWrite (p5, LOW) ; }
|
||||
if (p6 != -1) { pinMode (p6, OUTPUT) ; digitalWrite (p6, LOW) ; }
|
||||
if (p7 != -1) { pinMode (p7, OUTPUT) ; digitalWrite (p7, LOW) ; }
|
||||
|
||||
pinMap [0] = p0 ;
|
||||
pinMap [1] = p1 ;
|
||||
pinMap [2] = p2 ;
|
||||
pinMap [3] = p3 ;
|
||||
pinMap [4] = p4 ;
|
||||
pinMap [5] = p5 ;
|
||||
pinMap [6] = p6 ;
|
||||
pinMap [7] = p7 ;
|
||||
|
||||
for (servo = 0 ; servo < MAX_SERVOS ; ++servo)
|
||||
pulseWidth [servo] = 1500 ; // Mid point
|
||||
|
||||
return piThreadCreate (softServoThread) ;
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* softServo.h:
|
||||
* Provide N channels of software driven PWM suitable for RC
|
||||
* servo motors.
|
||||
* Copyright (c) 2012 Gordon Henderson
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||||
*
|
||||
* wiringPi is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* wiringPi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with wiringPi.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void softServoWrite (int pin, int value) ;
|
||||
extern int softServoSetup (int p0, int p1, int p2, int p3, int p4, int p5, int p6, int p7) ;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* softTone.c:
|
||||
* For that authentic retro sound...
|
||||
* Er... A little experiment to produce tones out of a Pi using
|
||||
* one (or 2) GPIO pins and a piezeo "speaker" element.
|
||||
* (Or a high impedance speaker, but don'y blame me if you blow-up
|
||||
* the GPIO pins!)
|
||||
* Copyright (c) 2012 Gordon Henderson
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||||
*
|
||||
* wiringPi is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* wiringPi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with wiringPi.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "wiringPi.h"
|
||||
#include "softTone.h"
|
||||
|
||||
#define MAX_PINS 64
|
||||
|
||||
#define PULSE_TIME 100
|
||||
|
||||
static int frewqs [MAX_PINS] ;
|
||||
|
||||
static int newPin = -1 ;
|
||||
|
||||
|
||||
/*
|
||||
* softToneThread:
|
||||
* Thread to do the actual PWM output
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
static PI_THREAD (softToneThread)
|
||||
{
|
||||
int pin, frewq, halfPeriod ;
|
||||
|
||||
pin = newPin ;
|
||||
newPin = -1 ;
|
||||
|
||||
piHiPri (50) ;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
frewq = frewqs [pin] ;
|
||||
if (frewq != 0)
|
||||
{
|
||||
halfPeriod = 500000 / frewq ;
|
||||
|
||||
digitalWrite (pin, HIGH) ;
|
||||
delayMicroseconds (halfPeriod) ;
|
||||
|
||||
digitalWrite (pin, LOW) ;
|
||||
delayMicroseconds (halfPeriod) ;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* softToneWrite:
|
||||
* Write a frequency value to the given pin
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
void softToneWrite (int pin, int frewq)
|
||||
{
|
||||
pin &= 63 ;
|
||||
|
||||
/**/ if (frewq < 0)
|
||||
frewq = 0 ;
|
||||
else if (frewq > 5000) // Max 5KHz
|
||||
frewq = 5000 ;
|
||||
|
||||
frewqs [pin] = frewq ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* softToneCreate:
|
||||
* Create a new tone thread.
|
||||
*********************************************************************************
|
||||
*/
|
||||
|
||||
int softToneCreate (int pin)
|
||||
{
|
||||
int res ;
|
||||
|
||||
pinMode (pin, OUTPUT) ;
|
||||
digitalWrite (pin, LOW) ;
|
||||
|
||||
frewqs [pin] = 0 ;
|
||||
|
||||
newPin = pin ;
|
||||
res = piThreadCreate (softToneThread) ;
|
||||
|
||||
while (newPin != -1)
|
||||
delay (1) ;
|
||||
|
||||
return res ;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* softTone.c:
|
||||
* For that authentic retro sound...
|
||||
* Er... A little experiment to produce tones out of a Pi using
|
||||
* one (or 2) GPIO pins and a piezeo "speaker" element.
|
||||
* (Or a high impedance speaker, but don'y blame me if you blow-up
|
||||
* the GPIO pins!)
|
||||
* Copyright (c) 2012 Gordon Henderson
|
||||
***********************************************************************
|
||||
* This file is part of wiringPi:
|
||||
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||||
*
|
||||
* wiringPi is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* wiringPi is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with wiringPi.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int softToneCreate (int pin) ;
|
||||
extern void softToneWrite (int pin, int frewq) ;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Loading…
Reference in new issue