Raspberry Pi Research

Simple GPIO test


Original gEDA schematic

Modified from RPi Low-level peripherals:
//
//  How to access GPIO registers from C-code on the Raspberry-Pi
//  Example program
//  15-January-2012
//  Dom and Gert
//  Revised: 15-Feb-2013


// Access from ARM Running Linux

#define BCM2708_PERI_BASE        0x3F000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */


#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

int  mem_fd;
void *gpio_map;

// I/O access
volatile unsigned *gpio;


// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))

#define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0

#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH

#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock

void setup_io();

void printButton(int g)
{
  if (GET_GPIO(g)) // !=0 <-> bit is 1 <- port is HIGH=3.3V
    printf("Button pressed!\n");
  else // port is LOW=0V
    printf("Button released!\n");
}

int main(int argc, char **argv)
{
  int g,rep;

  // Set up gpi pointer for direct register access
  setup_io();

  // Switch GPIO 7..11 to output mode

 /************************************************************************\
  * You are about to change the GPIO settings of your computer.          *
  * Mess this up and it will stop working!                               *
  * It might be a good idea to 'sync' before running this program        *
  * so at least you still have your code changes written to the SD-card! *
 \************************************************************************/

  // Set GPIO pins 7-11 to output
  for (g=17; g<=21; g++)
  {
    INP_GPIO(g); // must use INP_GPIO before we can use OUT_GPIO
    OUT_GPIO(g);
  }

  for (rep=0; rep<100; rep++)
  {
     g=21;
       GPIO_SET = 1<<g;
	printf ("Setting %d\n", g);
       usleep(100000);
       GPIO_CLR = 1<<g;
	printf ("Clearing %d\n", g);
       usleep(100000);
  }

  return 0;

} // main


//
// Set up a memory regions to access GPIO
//
void setup_io()
{
   /* open /dev/mem */
   if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
      printf("can't open /dev/mem (sudo?)\n");
      exit(-1);
   }

   /* mmap GPIO */
   gpio_map = mmap(
      NULL,             //Any adddress in our space will do
      BLOCK_SIZE,       //Map length
      PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
      MAP_SHARED,       //Shared with other processes
      mem_fd,           //File to map
      GPIO_BASE         //Offset to GPIO peripheral
   );

   close(mem_fd); //No need to keep mem_fd open after mmap

   if (gpio_map == MAP_FAILED) {
      printf("mmap error %d\n", (int)gpio_map);//errno also set!
      exit(-1);
   }

   // Always use volatile pointer!
   gpio = (volatile unsigned *)gpio_map;


} // setup_io


Trinary testing


Original gEDA schematic

int main(int argc, char **argv)
{
    int rep;
    int g;

    setup_io();

    for (rep=0; rep<100; rep++)
    {
	g=21;

	printf ("OFF %d\n", g);
	INP_GPIO(g);
	usleep(100000);

	GPIO_SET = 1<<g;
	printf ("HIGH %d\n", g);

	OUT_GPIO(g);
	usleep(100000);

	printf ("OFF %d\n", g);
	INP_GPIO(g);
	usleep(100000);

	GPIO_CLR = 1<<g;
	printf ("LOW %d\n", g);

	OUT_GPIO(g);
	usleep(100000);
    }

    return 0;
}


PWM testing on a motor


Original gEDA schematic

const unsigned long MARK = 100;
const unsigned long SPACE = 5000;


    for (;;)
    {
        g=21;

        INP_GPIO(g);
        usleep(SPACE);

        GPIO_SET = 1<<g;

        OUT_GPIO(g);
        usleep(MARK);

    }





Analogue Input with ADC Chip


Original gEDA schematic

Latest version of mcp3008.cpp:


507 6 8 8 8 7 9 14 
507 12 14 14 14 12 16 25 
507 16 18 19 20 17 22 34 
507 11 12 13 13 10 12 19 
507 6 7 7 7 5 6 9 
507 5 6 7 6 4 4 5 
507 3 4 5 4 3 2 2 
507 2 3 4 4 2 1 1 
507 1 2 3 3 1 0 0 
507 0 0 2 0 0 0 0 
507 10 11 13 13 12 14 19 
507 13 14 15 16 13 17 27 
507 0 0 0 0 0 0 0 
507 3 4 5 5 5 6 11 
507 6 7 8 8 6 8 13 
507 7 8 9 9 7 9 15 
507 8 9 9 9 8 10 17 
507 10 11 12 12 11 14 22 
507 9 10 10 10 9 11 17 
507 9 10 11 11 9 12 18 
507 9 10 10 10 8 10 15 
507 7 8 9 8 7 8 11 


Original gEDA schematic


Hardware PWM

The Pi has 2 hardware PWM channels.
These can be accessed using the wiringPi library.

#include <wiringPi.h>

int main (void)
{
    wiringPiSetup ();

    pinMode (1, PWM_OUTPUT); // Channel 0 (Board pin 12)
    pinMode (23, PWM_OUTPUT); // Channel 1 (Board pin 33)

    pwmSetMode (PWM_MODE_MS);
    pwmSetClock (2);
    pwmSetRange (1024);

    pwmWrite (1, 255); // 25%
    pwmWrite (23, 767); // 75%
}

root@raspberrypi:/home/pi# gcc pwmtest.c -l wiringPi -o pwmtest && ./pwmtest 
root@raspberrypi:/home/pi#


This runs at approx 26kHz

Using DMA to implement hardware PWM ServoBlaster
Basically this allows us to have many PWM channels on arbitary pins.

This was a quick feasibility test

The PWM frequency was 1kHz with resolution of 500 steps, and the 3-phase frequency is 74Hz.


Touchscreen Monitor Programming

This is not using the official touchscreen, but a 21 inch touchscreen monitor.


Latest version of triangle_rpi4.cpp:


Raspberry Pi 4 uses OpenGLES 2.0 and Shader Language GLSL 1.10

Arduino Due on a Raspberry Pi


There's a bug which I'm working out.

USB connection to Arduino using prototyping connectors


Power from 12vDC using a buck converter module


Latest version of gpio.c: