Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Saturday, June 20, 2015

Pi user space SPI

I finally had some time to play with a OLED (same one as my I2C one; SSD1306 chip), but this interface was SPI. I wanted to learn more about SPI and write a user space program in C++ that would run on my Raspberry Pi and drive the SPI OLED just like I had done for my I2C OLED. Did some digging on spidev and learned a lot. The commands to the OLED were the same as the I2C so I did not have to re-invent the wheel there, but the communication was the only difference.









Monday, July 8, 2013

GPIO using the Raspberry Pi


After getting my OLED and GPS working, I wanted to mess around with the GPIO pins so I bit off something simple. Here is what my setup looks like.
  • Raspberry Pi
  • Raspberry Pi T Cobbler
  • Raspberry Pi Ribbon Cable
  • Breadboard
  • Two 1 KiloOhms resistors
  • Two 10 KiloOhms resistors - pull up resistors
  • 2 momentary pushbuttons
  • Jumper wires
In this setup, pushing the button will drive the signal low. To keep things simple and just illustrate the point, pushing the button(s) will just print out a message to stdout. In doing some research, I came across Gordon's wiringPi library. I incorporated this into my code so I didn't have to reinvent the wheel! It is pretty simple to use for my C++ application. I started out the simple way and had a loop to check the pin status and act upon it if it has changed. However, that doesn't fit my end goal so I got a bit fancier with the implementation, but the good news is that it is supported by wiringPi. The fancier implementation is to use interrupts and to have a function pointer called when the interrupt is detected. Below is the code to drive this circuit. Currently, the circuit does bounce so debouncing code will need to be added to normalize this, but hopefully this illustrates the point.
#include <iostream>
#include <wiringpi.h>

// These are wiringPi pin numbers from http://wiringpi.com/pins
#define BUTTON_1     7  // pin 7 on pi
#define BUTTON_2     3  // pin 15 on pi

using namespace std;

void interruptHandler ()
{
   cout << "in interruptHandler()" << endl;
}

void interruptHandler2 ()
{
   cout << "in interruptHandler2()" << endl;
}

int main ()
{
   if (wiringPiSetup() < 0)
   {
      cout << "uniable to initialize wiringPi library!" << endl;
      return 1;
   }

   if (wiringPiISR (BUTTON_1, INT_EDGE_FALLING, &interruptHandler) < 0)
   {
      cout << "Unable to register interrupt handler for BUTTON_1!" << endl;
      return 1 ;
   }

   if (wiringPiISR (BUTTON_2, INT_EDGE_FALLING, &interruptHandler2) < 0)
   {
      cout << "Unable to register interrupt handler for BUTTON_2!" << endl;
      return 1 ;
   }

   // wait for interrupt, but don't consume 100% of cpu
   while (1)
      delay (100);

   return 0;
}

Friday, June 7, 2013

Reformat SD card after using it in Raspberry Pi

If you try to use your SD card after having used in your Raspberry Pi, you will notice your OS will not recognize it. OS X and Windows, it's pretty straight forward to reformat, but Linux is a bit more tricky, but here are the steps.
  1. Mount the SD card
  2. Find where the SD card is mounted. You can do this with the
    mount
    command. If you are not root, try
    sudo mount
    The SD card will be mounted to something like
    /dev/sdbx
    where x is a number.
  3. Delete the partitions from the SD card. The command to do this is
    sudo fdisk /dev/sdbx
    • p is the command to list the existing partitions
    • d is the command to delete the partition
    • delete all partitions on SD card
  4. Create a new partition
    • n is the command to create a new partition
    • p is the command to to create a primary partition
    • Enter the sector size 8192
    • press Enter to select the default last sector
    • t is the command to change the partition type
    • We want FAT32, so type b
    • w is the command to write the changes to disk
  5. Now we have our partition created, we need to format it. We can do that using this command
    mkdosfs -vF 32 /dev/sdb1
  6. That is it. You should now see this drive as a thumb drive again.

Wednesday, June 5, 2013

Linux IPC

I needed a way for my raspi program to communicate with with some events from the GPIO. Some options that quickly come to mind are sockets, shared memory, files, and signals. I wanted to briefly share an example in c++ using signals. For this example, we will use the SIGUSR1 signal, which by default, will terminate your application if not caught.

Lets create the signal handler. Pretty straight forward... If we get the SIGUSR1 signal, print out a message to stdout
// signal handler function
void sig_handler (int signo)
{
   if (signo == SIGUSR1)
      cout << "got SIGUSR1" << endl;
}

Next, we need to tell our application to listen for the signal. We do that by calling signal(). If we try to register our listener and something fails or a that signal can't be listened to, we will see an error message printed out to stdout. Note, not all message can be trapped and acted upon. For example, SIGKILL can't be caught. If you were to try and register a listener for it (I encourage you to do so), you will see it will fail.
if (signal(SIGUSR1, sig_handler) == SIG_ERR)
      cout << "Unable to catch SIGUSR1" << endl;

Now, if we put this all together and run our program, we can try to send the SIGUSR1 signal and see if we trap it in our application. Here is a complete example (signal-receiver.cpp).
#include <iostream>
#include <signal.h>
#include <stdio.h>

using namespace std;

// signal handler function
void sig_handler (int signo)
{
   if (signo == SIGUSR1)
      cout << "got SIGUSR1" << endl;
}

int main()
{
   if (signal(SIGUSR1, sig_handler) == SIG_ERR)
      cout << "Unable to catch SIGUSR1" << endl;

   // simulate a long process - calling sleep() so CPU doesn't go to 100%
   while (1)
      sleep(1);

   return 0;
}

To compile, nothing special.
g++ -Wall signal-receiver.cpp -o signal-receiver 

Run and send the SIGUSR1 signal. Notice the program does not terminate upon receiving the signal. You can send it over and over and it will not terminate. Try commenting out the adding of the listener in the program above, re-compile, and run. When you send the SIGUSR1 signal, it will terminate your application.
$ ./signal-receiver 
got SIGUSR1
got SIGUSR1
got SIGUSR1

To send the signal from the command line
$ kill -USR1 <PID>

Lastly, if you are curious if you can send a signal from another c++ program, the answer is yes! Here is a simple example.
#include <iostream>
#include <signal.h>

using namespace std;

int main (int argc, char* argv[])
{
   if (argc != 2)
   {
      cout << "Usage: " << argv[0] << " <PID>" << endl;
      return 1;
   }
   int ret;
   ret = kill(atof(argv[1]), SIGUSR1);
   if (!ret)
      cout << "Successfully sent signal";
   else
      cout << "Error sending signal";
   cout << endl;
   return 0;
}