## Week 11: Teaching the Fab-Pic to read

In week 11 we had the task to measure something with an microcontroller. Well, we also should create our one board for this, so i used the fab-pic again. Lucky for you ;)
This way you will get some code-snipletts more for your first steps in the PIC-World...

My first idea was to realise a kind of touch-screen.

The theory behind this is a capacitive-touch-sensor, made out of a piece of FR4 or any other metal and a resistor. The sensor (the piece of metal) is connected with an input-pin equiped with a schmitt-trigger. The sensor is also connected to ground by a very high resistor, 1 mega-ohm by example.
The touch-sense itself is all made by the software in a loop:

• Config the pin as output and make it high. The selfmade capacitor = the metal piece is charged up
• wait a little bit for the charge to finish (5µs or so)
• config the pin as an input
• wait until the pin is a 0
• repeat

• So, what is happening here? The metal-piece is building a capacitor with the air around it. In the moment the Output-Pin is configed as an input the charge of this capacitor flows thru the very high resistance of the input-pin and thru the 1 mega-ohm resistor. Like every capacitor discharging this will happen in a inversed e-function.
The schmitt-trigger on the input will tell a 0 for the input at a defined voltage of this function. If we combine this with a timer we can measure very exact the time of this discharge.

But what happens if you put your finger on the metal-piece? Right, you change the capacitor and the discharge-time...
The PIC-Code for this loop is quite easy:

``` temp = 0; for(i=0; i<5; i++)      {      TRISCbits.TRISC0 = 0;     //Set B0 to output      PORTCbits.RC0 = 1;     //load the sensor-element      __delay_ms(1);     //wait for the cap to load      WriteTimer1(0x0);     //Reset Timer 1      T1CONbits.TMR1ON = 1;     //Start Timer1      TRISCbits.TRISC0 = 1;     //Set C0 to to input      while (PORTCbits.RC0 == 1);     //wait for discharge      T1CONbits.TMR1ON = 0;     //Stop Timer1      temp = temp + ReadTimer1();      __delay_ms(1);      } button_1 = temp / 5; ```

This works suprisingly good, but not on a bread board. I tried it out and there is no chance to get it working, because of all the capacitance in the board, emv into the cables between the bread-board and the sensor-board and so on.

Doo´h!!!

If you still want to try it on your own (maybe without the breadboard!), here are the eagle-files for the sensor-board:
ZIP-File

UPDATE
Ok, after the review with Barcelona i learnd, that Neil explained such a sensor circuit in the conference last week.
But there is still one big difference: Neil uses the ADC to convert the whole discharging-curve. In my circuit, i use the Schmitt-trigger-inputs and the timer to measure the lenght of the discharging-curve. This way i can use an interrupt for the measurement and the conversion will be much faster.
The schmitt-tiggers are needed to compare the curve to a defined voltage-level.
Here is a simple sketch to explain it graphicaly:

Again, lucky for you ;)
After the touch-sensor-sh** i decided to make a short AD-Conversion, and give it out via the USART of the pic. I split this into two sections:

#### The USART

The XC8-Compiler comes with some peripheral functions, also a few for the USART. The Fab-Pic has 2 of these USARTs, we will use the first one. As you can see in the datasheet this is connected to pin RC7(receive) and pin RC6(transmit), on the Fab-Pic Pin 18 and 17.
So these are the pins you can hook up your FTDI-Cable onto.
As every peripheral-function we have to config the USART before we can use it.
To make it simple, here is the commented code:

``` Open1USART     //Init USART 1     (USART_TX_INT_OFF &     //Send-Interrupt off      USART_RX_INT_OFF &     //Receivce-Interrupt off      USART_ASYNCH_MODE &      USART_EIGHT_BIT &      USART_CONT_RX &      USART_BRGH_HIGH, 16);      //Baud 16 => 115.200 ```

Now you can use some USART-Commands like getch. To make it more comfortable you can add a subroutine to your program:

``` //needed by printf, used to configure the destination void putch(char data) {      while( ! TXIF)      // check buffer      continue;      // wait till ready      TXREG = data;      // send data     } ```

This routine is used by the printf-function. Here you define were the printf should print to, USART1 or USART2 or LCD or or or...

In this case the printf is patched to the USART1, the one we use. The usage is easy and standard c:

``` printf("This is Fab-Pic!\n"); //Say hello to the world! ```

To read something you have to wait until a character is received. The flag for the USART1 can be found PIR1bits.RC1IF. Take a look in the datasheet under "interrupts" to find the flags for other interfaces. As soon as a character is recieved, you can read it with "getc1USART()". If you want to read in a string use "gets1USART(destination, length)", so b.e. "gets1USART(char string[5], 5)".

```     while (PIR1bits.RC1IF != 1);     //wait until USART received data     some_number = getc1USART();     //read in the received char ```

The Fab-Pic has 8 ADC-Channels with a resolution of 12-Bit.
The init of the ADC is not very complex, i will show it by hand and not by using one of the plibs.
In my oppinion it is easyer to write the registers by hand so you know exactly what happens

In this example we will use only the AN0 input pin. The config:

```     ANCON1 = 0b00000000;     // Just AN0 is an analog input, all other pins are digital     ADCON1 = 0b00000000;     //No special triggers, Ref is Vdd and Vss     ADCON2 = 0b10111100;     //result is right justified, 8 Tads, Clock = 32Mhz / 4     ADCON0 = 0b00000001;     //Select AD0 for all AD-Operations ```

After the init we can use the ADC by the following code:

```     ADCON0 = 0b00000001;     //Select AD-Channel 0     ConvertADC();     //start AD-Conversion     while(BusyADC());     //wait for conversion to finish     adc_result = ((ADRESH)<<8)|(ADRESL);    //read in the result     adc_result = (adc_result * 1.22);    //make mV out of the adc-value ```

For a test i connected a potentiometer to AN0, Vdd and Vss. Then i put the USART and the ADC snipletts together

And this is the result in a terminal:

#### I2C

As a little extra here is some uncommented Code for using the I2C-Interface:
Init:

``` // I2C-Init OpenI2C(MASTER, SLEW_OFF);     // Initialize I2C module SSPADD = 19;     //100kHz = 79, 400khz = 19 ```

And the for code to read out a MCP3221 ADC from Microchip:

``` // Routine for readout of ADC MCP3221 by I2C unsigned int adchanger(void) {      unsigned int highbyte, lowbyte, adc;      highbyte = lowbyte = adc = 0;      StartI2C();    //Send a start-condition      while (SSPCON2bits.SEN);    //Wait for finishing the start-condition      WriteI2C(0b10011011);    //Send the MCP the command to start a conversion      while (SSPCON2bits.ACKSTAT);    //Wait for the ACK from the ADC      highbyte = ReadI2C();     //Read in the highbyte      IdleI2C();    //wait the readout to finish      AckI2C();    //send a ACK to the ADC      IdleI2C();    //wait for finish      lowbyte = ReadI2C();    //read in the lowbyte      IdleI2C();    //Wait for finisch      StopI2C();    //Send the stop-condition      while (SSPCON2bits.PEN);     //Wait for finishing the stop-condition      highbyte = (highbyte << 8);     //Converse the High and Lowbyte into one unsigned int      adc = (highbyte | lowbyte);      return (adc); } ```

I hope this make some things for you easier...