Friday, June 14, 2019

Race Lights

This is used for an RC racing light tree.  It stays red until you push the button, then stays yellow for 1-3 seconds (randomly), then flashes all colors twice, then stays green until you push the button.  Weak pull-ups are enabled on pin 5 for the button.

/* 
 * File:   RaceLightsMain.c
 * Author: hmikelson
 *
 * Created on June 14, 2019, 1:26 PM
 */

#if defined(__XC)
    #include <xc.h>         /* XC8 General Include File */
#elif defined(HI_TECH_C)
    #include <htc.h>        /* HiTech General Include File */
#endif

#include <stdint.h>        /* For uint8_t definition */
#include <stdbool.h>       /* For true/false definition */
#include <stdlib.h>     /*rand()*/

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 4000000
uint8_t sGPIO;

void init()
{
    //Configure GPIO Port
    ANSEL =  0b00000000;  //Configure all GPIO pins as digital
    TRISIO = 0b11101000;  //Set GP3 & 5 as input and the rest as outputs
    OPTION_REGbits.nGPPU = 0;
    WPU = 0b00100000;     //Enable weak pullups on GP5
    //Configuer AD Convertor
    ADCON0 = 0x00;        //AD disabled
    ADRESH = 0x00;        //Init the AD Register
    //Configure Comparator
    CMCON0 = 0xFF;   // Comparator is turned off
    CMCON1 = 0x00;   // Comparator is turned off
    //Interrupt configuration
    INTCON = 0x00;   //Disable all interrupts
}

void vdelay(int n)
{
    int i;
    for (i=0;i<=n;i++)
    {
     __delay_ms(150);
    }
}

void main()
{
uint8_t r, db_cnt;

 init();
 GPIO = 0b00000001;
 __delay_ms(100);
 GPIO = 0b00000010;
 __delay_ms(100);
 GPIO = 0b00000100;
 __delay_ms(100);
 GPIO = 0b00000000;                                      
 while(1)
  {
   GPIO = 0b00000001;
   __delay_ms(200);
   for (db_cnt = 0; db_cnt <= 10; db_cnt++)
    {
     __delay_ms(10);
     if (GPIObits.GP5 == 1)
      db_cnt = 0;
    }
   GPIO = 0b00000010;
   r = rand()%15;
   __delay_ms(250);
   vdelay(r);
   __delay_ms(250);
   GPIO = 0b00000001;
   __delay_ms(50);
   GPIO = 0b00000010;
   __delay_ms(50);
   GPIO = 0b00000100;
   __delay_ms(50);
   GPIO = 0b00000001;
   __delay_ms(50);
   GPIO = 0b00000010;
   __delay_ms(50);
   GPIO = 0b00000100;
   __delay_ms(50);
   GPIO = 0b00000100;
   __delay_ms(200);
   for (db_cnt = 0; db_cnt <= 10; db_cnt++)
    {
     __delay_ms(10);
     if (GPIObits.GP5 == 1)
      db_cnt = 0;
    }   
  }
}

Sunday, March 3, 2019

Back Up Robot

Code for autonomous robot with PIR motion detection and ultrasound distance sensor.  Distance sensing decreases the chance of the robot getting stuck.  Robot also plays sounds while moving.

/* 
 * File:   BackupBotMain.c
 * Author: hmikelson
 *
 * Created on January 12, 2019, 11:32 AM
 * 
 * This program is used to control a robot with PIC16f1825 microcontroller
 * Uses a customized circuit board with a 1 watt amplified speaker
 * high intensity LED
 * Ultrasound sensor, and PIR sensor
 * Two motors: Forward, backward, right, left, stop
 * 6V battery power
 * Gear driven wheels
 */

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSC
#define _XTAL_FREQ 16000000
unsigned char sPORTA=0b00000000, sPORTC=0b00000000, pwmax=63;

void init()
{
 //Configure GPIO Port
 //RA0=BI2,RA1=BI1,RA2=Stby,RC0=AI1,RC1=AI2,RC2=PWMA&B
 //RC3=PIR,RC4=Trig,RC5=Echo,RA3=NA,RA4=Audio,RA5=LED
 //ANSELC= 0b00000000; //Must disable analog inputs to read digital in
 TRISA = 0b11000000;  //O=all
 TRISC = 0b11101000; //I=3,5
 OSCCONbits.IRCF = 0b1111;
 OSCCONbits.SCS = 0b00;
 //Enable analog input on C3
 ANSELCbits.ANSC3 = 1;
 ADCON0 = 0b00011101; //Channel (CHS4:0 bits 6-2),ADON bit 1 enable Analog
 ADCON1bits.ADCS = 0b111; // clock select dedicated osc 
 ADCON1bits.ADNREF = 0; //neg ref
 ADCON1bits.ADPREF = 0; //config + voltage with vdd
 ADCON1bits.ADFM = 1; //format left justified
 ADRESH = 0x00;        //Init the AD Register
}

void vdelay(int n)
 {
  int i;
  for (i=0;i<=n;i++)
   {
    __delay_us(5);
   }
 }

// Read voltage from input
int read_v()
 {
  int val,v1,v2;
  __delay_ms(1);
  ADCON0bits.GO_nDONE = 1;
  while(ADCON0bits.GO_nDONE == 1);
  return (ADRESH<<8) + ADRESL;
 }

/* 
 * Get distance from ultra sound sensor
 * Sensor on pins C4 Trig, C5 Echo
 * 
 */
int getdist()
 {
  int i=0;
  sPORTC = sPORTC & 0b11101111;
   PORTC = sPORTC;
   __delay_us(40);
  sPORTC = sPORTC | 0b00010000;
   PORTC = sPORTC;
   __delay_us(10);
  sPORTC = sPORTC & 0b11101111;
   PORTC = sPORTC;
  while((PORTCbits.RC5 == 0) && (i<5000)) //Wait but not forever
   {
    i++;
   }
  i=0;
  while ((PORTCbits.RC5 == 1) && (i<1000)) //Wait but not forever
   {
    i++;
   }
  return i;
 }

// Drive robot forward
void RobotFd(int time, unsigned char speed)
 {
  int i, j;
  for (i=0;i<time;i++)
   {
    for (j=0;j<pwmax;j++)
     {
      if (j<speed)
       {
         PORTA = 0b00111110;  // LED,Aud,MCLR,En,BI2,BI1
        sPORTC=0b00000110 | sPORTC;
        sPORTC=0b11111110 & sPORTC;
         PORTC = sPORTC;  // Eco,Trg,PIR,PWM,AI1,AI2
        vdelay(pwmax/speed);
       }
      else
       {
         PORTA = 0b00000110;
        sPORTC = 0b00000010 | sPORTC;
        sPORTC = 0b11111010 & sPORTC;
         PORTC = sPORTC;
        vdelay(pwmax/speed);
       }       
     }    
   }
 }

// Move Robot backward
void RobotBk(int time, unsigned char speed)
 {
  int i, j;
  for (i=0;i<time;i++)
   {
    for (j=0;j<pwmax;j++)
     {
      if (j<speed)
       {
         PORTA = 0b00111101;
        sPORTC = 0b00000101 | sPORTC;
        sPORTC = 0b11111101 & sPORTC;
         PORTC = sPORTC;
        vdelay(pwmax/speed);
       }
      else
       {
         PORTA  = 0b00000101;
        sPORTC = 0b00000001 | sPORTC;
        sPORTC = 0b11111001 & sPORTC;
         PORTC = sPORTC;
        vdelay(pwmax/speed);
       }       
     }      
   }
 }

// Move the robot right for time at speed.
void RobotRt(int time, unsigned char speed)
 {
  int i, j;
  for (i=0;i<time;i++)
   {
    for (j=0;j<pwmax;j++)
     {
      if (j<speed)
       {
         PORTA = 0b00111110;
        sPORTC = 0b00000101 | sPORTC;
        sPORTC = 0b11110101 & sPORTC;
         PORTC = sPORTC;
        vdelay(pwmax/speed);
       }
      else
       {
         PORTA = 0b00000110;
        sPORTC = 0b00000001 | sPORTC;
        sPORTC = 0b11111001 & sPORTC;
         PORTC = sPORTC;
        vdelay(pwmax/speed);
       }        
     }        
   }
 }

//Move the Robot Left for given time and speed.
void RobotLt(int time, unsigned char speed)
{
 int i, j;
 for (i=0;i<time;i++)
  {
   for (j=0;j<pwmax;j++)
    {
     if (j<speed)
      {
        PORTA = 0b00111101;
       sPORTC = 0b00000110 | sPORTC;
       sPORTC = 0b11111110 & sPORTC;
        PORTC = sPORTC;
       vdelay(pwmax/speed);
      }
     else
      {
        PORTA = 0b00000101;
       sPORTC = 0b00000010 | sPORTC;
       sPORTC = 0b11111010 & sPORTC;
        PORTC = sPORTC;        
       vdelay(pwmax/speed);
      }      
    }     
  }
}

// Robot stops for the given amount of time
void RobotSt(int time)
{
    int i;
    for (i=0;i<time;i++)
     {
      PORTA = 0b00000100;
      sPORTC = 0b00000100 | sPORTC;
      sPORTC = 0b11111100 & sPORTC;
      PORTC = sPORTC;
      __delay_ms(10);
     }

}

void main()
 {
  int mt=100,dist=1000,i;
  unsigned char rspeed, raction, rtime, nacts=30, pir;
  init();

  RobotFd(200,pwmax/1.5);
  RobotRt(200,pwmax/1.5);
  RobotBk(200,pwmax/1.5);
  RobotLt(200,pwmax/1.5);
  while(1)
   {
    while (nacts==0)
     {
      RobotSt(200);
      pir = read_v();
      if (pir>50)
       {
        nacts = 30;
       }           
     }
    dist = getdist();
    if (dist<300)
     {
      RobotBk(mt,pwmax/2);
      RobotRt(mt,pwmax/2);
     }
    else
    {
     RobotFd(mt,pwmax/2);
    }
    nacts = nacts - 1;
    raction=(rand() % 5);
    rtime=(rand() % mt)/2+mt/2;
    rspeed=pwmax/((rand() % 15)+1)+pwmax/5;
    switch (raction)
     {
      case 1:
       RobotFd(rtime,rspeed);
       break;
      case 2:
       RobotBk(rtime,rspeed);
       break;
      case 3:
       RobotLt(rtime,rspeed);
       break;
      case 4:
       RobotRt(rtime,rspeed);
       break;
      default:
       RobotSt(rtime);
       break;
      }
  }
 }