Friday 24 March 2017

Playing Video on Raspberry Pi

So you have a new raspberry pi, it is all set up, something like Raspbian is running on the SD card, and you have a desktop in front to of you. You might have even played with some of it, maybe one of the built in games. I know the first thing I wanted to do was to play a video. There doesn't seem to be a video player on the dropdown menu, but there is one built in, To get to it, the terminal is needed. I know it seems kinda scary, but its just one line.

Firstly, you need to know where the video is that you want to play. I have mine on a memory stick in the USB port. When the memory stick is plugged in, it will usually open in the file manager. In the bar at the top it will show the file path, mine is shown below as an example.

/media/pi/memstick/
Also, note the name of the file you want to play, and the way it is encoded. So it might be a .mp4 or a .avi or anything similar. If you want to play an uncommonly encoded video, look at the omxplayer documentation to check it supports it.

The next part is easy, open up the terminal, and type in:

omxplayer -o hdmi /media/pi/memstick/hk3.avi
Note the last bit is the file path, and will be different depending on where your file is stored; the above is an example. Just to explain what is going on here, omxplayer is the command we are using, and uses the already installed application associated with it. -o opens the port, and hdmi tells the pi where the stream needs to be output to (remember the pi has a few video outs). This command also allows the audio to play through the hdmi.

All going well, a video will play. Note you cant use the mouse to control the video, it is all done run through the terminal, so pressing keys controls what you want to do. A short list of commands is shown below.

1                    decrease speed
2                    increase speed
<                    rewind
>                    fast forward
z                     show info
j                     previous audio stream
k                    next audio stream
i                     previous chapter
o                    next chapter
n                    previous subtitle stream
m                   next subtitle stream
s                     toggle subtitles
w                    show subtitles
x                     hide subtitles
d                     decrease subtitle delay (- 250 ms)
f                      increase subtitle delay (+ 250 ms)
q                     exit omxplayer
p / space         pause/resume
-                      decrease volume
+ / =                increase volume
left arrow       seek -30 seconds
right arrow    seek +30 seconds
down arrow   seek -600 seconds
up arrow        seek +600 seconds


Friday 17 March 2017

Interfacing a PIC and a 16x2 LCD

So in a recent project I had to implement a 16x2 LCD  on a PIC16F1827, but the system will work on most PIC microcontrollers, with slight changes to the code. For this project I am using MPLAB X v3.40, a free development environment, and a PICKIT 3, which can be bought at a number of stores online.

Setting up the MPLAB project

  1. Start off by loading up MPLAB X, if you don't have it already, install it from the Microchip website microchip.com/mplab/mplab-x-ide.
  2. Start a new project, by going to File->New Project... or by pressing Ctrl+Shift+N
  3. The project we want is a standalone project, it should be chosen by default. Next choose the device we want, write in the box PIC16F1827 there should only be one. We want to use the PicKit 3 for the programmer. I am using XC8 as the compiler, this is available from the Microchip website. Finally choose the name of the project, and where you want to keep it. Then click finish.
  4. It wont look like mush at the moment, but under Projects on the right, there should now be your newly created project, with a drop down, and a set of folders. Something like this: 
  5. To start the project, we need a main.c. So right click on Source Files, go to New->C Main File... then in the Dialog, change the name to main. After pressing okay, it should look like this: 

Connecting the LCD

LCDs have what is known as a parallel connection. This means that we send data 8 bits at a time, rather than serial where it is one at a time. The datasheet for the PIC is found on the microchip website here. The pinout is found on page 4.

Register Select (RS) pin, this decides which of the two registers that is getting written to. Either the instruction register (what the screen does) or the data register (what is shown on the screen). This is connected to A4 on the PIC.
Read/Write (RW) pin, this decides whether you are writing to or reading from the LCD. This is connected to pin A3.
Enable (E) pin, is to tell the LCD when data needs to be transferred. Pulsing this pin will write or read to the registers the data on the data pins. This is connected to pin  A2.
These pins are defined at the top of the code, to make life easier for us later on.
#define LCD_RS LATAbits.LATA4   //LCD Command/Data Control
#define LCD_RW LATAbits.LATA3   //LCD Read/Write Select
#define LCD_E LATAbits.LATA2    //LCD Enable Line
Data Pins (D0-D7), are the pins that transfer the information between the LCD and the PIC. These are connected to pins B0-B7. So B0 is connected to D0, and so on until B7 is connected to D7.
Vdd and Vss are connected to 5v and GND respectively.
Contrast (Vo) is connected to a 10k pot between the 5v  and  GND.
If the LCD you are using has connections for a backlight, follow the datasheet for instructions, on mine I connect it t0 5v and GND.

The Code

Below is the function I create to send data to the LCD.
#define LCD_CMD 0
#define LCD_TXT 1 

void LCD_DATA (unsigned char data, int type)
{
    __delay_ms(100);   // short delay

    LATB = 0x00;       // reset the register to 0
    LATB = data;       // set B output to the data we want to send
    __delay_ms(1);     // short delay for data to set

    if (type == LCD_CMD)
    {
        LCD_RS = 0;    // command mode
    }
    else
    {
        LCD_RS = 1;    // character/data mode
    }

    LCD_RW = 0;        // start the pulse
    __delay_ms(1);     // small delay
    LCD_E = 1;         // enable LCD data line
    __delay_ms(1);     // small delay
    LCD_E = 0;         // disable LCD data line
    __delay_ms(5);
}
Calling this function in the main, like follows will send data to the LCD. Notice the #define at the top, these are declaring LCD_CMD and LCD_TXT. Basically, when the type is LCD_CMD the LCD is sent into command mode, by setting the RS pin. Equally, sending LCD_TXT will clear the RS pin, putting the LCD in character mode.
The information on the data pins will then get written to the LCD, by clearing RW. To actually tell the LCD that it needs to be sent new instructions the enable pin needs to be pulsed. Once this happens, the screen should be updated with the new information.
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#define _XTAL_FREQ 500000

#define LCD_RS LATAbits.LATA4   //LCD Command/Data Control
#define LCD_RW LATAbits.LATA3   //LCD Read/Write Select
#define LCD_E LATAbits.LATA2    //LCD Enable Line

#define LCD_CMD 0
#define LCD_TXT 1 

void LCD_DATA (unsigned char data, int type)
{
    __delay_ms(100);   // short delay

    LATB = 0x00;       // reset the register to 0
    LATB = data;       // set B output to the data we want to send
    __delay_ms(1);     // short delay for data to set

    if (type == LCD_CMD)
    {
        LCD_RS = 0;    // command mode
    }
    else
    {
        LCD_RS = 1;    // character/data mode
    }

    LCD_RW = 0;        // start the pulse
    __delay_ms(1);     // small delay
    LCD_E = 1;         // enable LCD data line
    __delay_ms(1);     // small delay
    LCD_E = 0;         // disable LCD data line
    __delay_ms(5);
}


int main(int argc, char** argv) {
 
    // write "hello world!" on the first line
    LCD_DATA('h', LCD_TXT);
    LCD_DATA('e', LCD_TXT);
    LCD_DATA('l', LCD_TXT);
    LCD_DATA('l', LCD_TXT);
    LCD_DATA('o', LCD_TXT);
    LCD_DATA(' ', LCD_TXT);
    LCD_DATA('w', LCD_TXT);
    LCD_DATA('o', LCD_TXT);
    LCD_DATA('r', LCD_TXT);
    LCD_DATA('l', LCD_TXT);
    LCD_DATA('d', LCD_TXT);
    LCD_DATA('!', LCD_TXT);
 
    while (1)
    {
 
    }
 
 return (EXIT_SUCCESS);
}