Sunday, November 4, 2018

This program creates a lighting effect that includes a very slow fade, strobe lights, and flashing lights.  It uses a 12f683 and pin 3 for input so you need to provide a pull up resistor (10k) and a pull down resistor (1k) when you push the button.  It  does not use an interrupt so you have to wait until the routine gets around to checking on the button, in other words you may have to hold the button down for a while especially during the slow cross fade.  Use a TIP31 for the LEDs (9V->LED->R->TIP31->Gnd) and a high current 7805 power regulator.  9V 2 A DC power supply.

/* 
 * File:   ls5main.c
 * Author: Hans Mikelson
 *
 * Created on December 17, 2014, 8:59 AM
 */

#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>        /* includes rand() */

#pragma config MCLRE=OFF,CP=OFF,WDTE=OFF,FOSC=INTOSCIO
#define _XTAL_FREQ 4000000
uint8_t sGPIO, gr1=0, gr2=0;  // Global shadow register and random variables

void init()
{
    //Configure GPIO Port
    ANSEL =  0b00000000;  //Configure all GPIO pins as digital
    TRISIO = 0b110001000;  //Set GP3 as input the rest as outputs
    OPTION_REGbits.nGPPU = 0;
    WPU = 0b00000000;     //Disable weak pullups
    //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) //Variable time delay
{
    int i;
    for (i=0;i<=n;i++)
    {
     __delay_us(100);
    }
}

void xfade(int n)  //Cross fade between two global random #s
{                  //n controls the very slow fade time
    int j, k, i;
        for (j=0;j<255;j++)
         {
          for (i=0;i<n;i++)
           {
            for (k=0;k<255;k++)
             {
              if (j<k)
               {
                GPIO=gr2;
               }
              else
               {
                GPIO=gr1;
               }
             }
           }
         }
        gr2 = gr1;
        gr1 = rand() & rand();
}

void strobe(int n)  //Create a strobing cross fade
{
    int j, k, i;
        for (j=0;j<63;j++)
         {
          for (i=0;i<1;i++)
           {
            for (k=0;k<63;k++)
             {
              if (j<k)
               {
                GPIO=gr2;
                vdelay(n);
               }
              else
               {
                GPIO=gr1;
                vdelay(n);
               }
             }
           }
         }
        gr2 = gr1;
        gr1 = rand() & rand();
}

void main()
{
    int i=1;
    init();
    GPIO = 0b00000000;

    while(1)
    {
     if (GPIObits.GP3 == 0)
      {
       i=(i+1) % 9;
       GPIO = 0b00000000;
       vdelay(10000);
      }
     switch (i)
      {
       case 1:                  //Medium flash
        GPIO = rand() & rand(); 
        vdelay(4000);
        break;
       case 2:                  //Fast flash 
        GPIO = rand() & rand();
        vdelay(2000);
        break;
       case 3:
           xfade(1);
        break;
       case 4:
           xfade(8);
        break;
       case 5:
           xfade(32);
        break;
       case 6:
           strobe(4);
        break;
       case 7:
           strobe(8);
        break;
       case 8:
           strobe(32);
        break;
      default:                    // Slow flash
       GPIO = rand() & rand();
       vdelay(8000);
       break;
      }
    }
}

Thursday, November 1, 2018

LED Strobe Light

This code is for a 12f683 pic, connected to TIP31 transistors and white LEDs.  It generates a variety of strobe effects.  Randomly it will create either darkness (none), synchronized strobe on both channels, random strobe on both channels, the duration of the on pulse and off pulse also varies randomly.  This makes a great Halloween effect.

/*
 * File:   strobemain.c
 * Author: hmikelson
 *
 * Created October 2016
 */

#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 = 0b11001000;  //Set GP3 as input and the rest as outputs
                    // GP0 = eye 1, GP2 = eye 2, GP5 = speaker, GP4 = piezo
    OPTION_REGbits.nGPPU = 0;
    WPU = 0b00000100;     //Enable weak pullups on GP2
    //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_us(1);
    }
}

void strobe1(int r)
{
 int i,n;
 n=200/r;
 for (i=0;i<n;i++)
  {
   GPIO = 0b11000011;
   vdelay(100);
   GPIO = 0b11000000;
   vdelay(r*1000);
  }
}

void strobe2(int r)
{
 int i,n;
 n=200/r;
 for (i=0;i<n;i++)
  {
   GPIO = 0b11000011;
   vdelay(200);
   GPIO = 0b11000000;
   vdelay(r*1000);
  }
}

void strobe3(int r)
{
 int i,n,r1;
 n=200/r;
 for (i=0;i<n;i++)
  {
   r1 = rand()%16;
   GPIO = 0b11000011;
   vdelay(100);
   GPIO = 0b11000000;
   vdelay(r1*1000);
  }
}

void strobe4(int r)
{
 int i,n,r1;
 n=200/r;
 for (i=0;i<n;i++)
  {
   r1 = rand()%16;
   GPIO = rand();
   vdelay(100);
   GPIO = 0b11000000;
   vdelay(r1*500);
  }
}

void darkness(void) // PWM sweep high f to low f
{
 GPIO = 0b11000000;
 __delay_ms(2000);
}

void main()
{
uint8_t r,r2;

 init();

 while(1)
  {
   r=rand()%8;
   //r=2;
   r2 = rand()%32+1;
   switch (r)
    {
     case 1:
     strobe1(r2);
     break;

     case 2:
     strobe2(r2);
     break;

     case 3:
     strobe3(r2);
     break;

     case 4:
     strobe4(r2);
     break;

     default:
     darkness();
    }
  }
}

 

Sunday, September 9, 2018

Robot Code

This is the operating code for a robot I built called Dumbot.  It only has a motion sensor and moves randomly.  The code generates three random numbers: speed, time, movement type.  There are five different movement types: Forward, backward, turn right, turn left, and stop.  There is a check routine at the  beginning: Forward, right, backward, left.  To check to make sure the motors are installed properly.  This code was tested on a PIC16F1825, using hobby motors from Sparkfun and the brushed motor controller breakout board from Sparkfun.  A switched battery holder with three double A batteries from Jameco was used.  The wheels and frame were 3D printed.  An LED output and an audio output were included.

/* 
 * File:   R06Main.c
 * Author: hmikelson
 *
 * Created on September 4, 2018, 6:11 PM
 */

#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, sPORTC, pwmax=31;

void init()
{
    //Configure GPIO Port
    TRISA = 0b110000000;  //Set all Output
    TRISC = 0b110001000; //Set up pin 3 for input
    OSCCONbits.IRCF = 0b1111;
    OSCCONbits.SCS = 0b00;
    //OPTION_REG = 0b01111111; //Global enable weak pullups
    //WPUC = 0b00001000;     //Enable weak pullups with a 1
    // Set up analog input
    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
    ADRESL = 0x00;       // I don't think this is needed

    //OSCCONbits.SPLLEN = 0b1;
}

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

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

// 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;  // 
                PORTC = 0b00010110;  // Enable on pin 4
                vdelay(pwmax/speed);
            }
            else
            {
                PORTA = 0b00000110; // I think there is a  clock output on pin 4 which I don't know how to disable
                PORTC = 0b00010010; // Enable on pin 4
                vdelay(pwmax/speed);
            }
            
        }
        
    }
}

// Drive 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;
                PORTC = 0b00010101;
                vdelay(pwmax/speed);
            }
            else
            {
                PORTA = 0b00000101;
                PORTC = 0b00010001;
                vdelay(pwmax/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;
                PORTC = 0b00010101;
                vdelay(pwmax/speed);
            }
            else
            {
                PORTA = 0b00000110;
                PORTC = 0b00001001;
                vdelay(pwmax/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;
                PORTC = 0b00110110;
                vdelay(pwmax/speed);
            }
            else
            {
                PORTA = 0b00000101;
                PORTC = 0b00001010;
                vdelay(pwmax/speed);
            }
            
        }
        
    }
}

void RobotSt(int time)
{
    int i;
    for (i=0;i<time;i++)
    {
    PORTA = 0b00000100;
    PORTC = 0b00001100;
    __delay_ms(10);
    }

}

void main()
 {
  int rmode, rtime, volts,mt=31;
  unsigned char rspeed, nactions=0;
  init();
  RobotFd(100,pwmax/2);
  RobotSt(1);
  RobotRt(100,pwmax/2);
  RobotSt(1);
  RobotBk(100,pwmax/2);
  RobotSt(1);
  RobotLt(100,pwmax/2);
  RobotSt(1);
  while(1)
   {
     if (nactions > 0)
     {
         rmode=(rand() & 7) + 1;
         nactions=nactions-1;
     }
     else
     {
         rmode = 0;
     }
     rtime = (rand() & 7)+1;
     rspeed = rand() & pwmax;
     switch (rmode)
      {
       case 1:
        RobotFd(rtime*mt,rspeed);
        RobotSt(1);
        break;
       case 2:
        RobotBk(rtime*mt,rspeed);
        RobotSt(1);
        break;
       case 3:
        RobotRt(rtime*mt,rspeed);
        RobotSt(1);
        break;
       case 4:
        RobotLt(rtime*mt,rspeed);
        RobotSt(1);
       break;
       case 0:
        RobotSt(1);
        volts = read_v();
        if (volts>50)
         {
            nactions = 10;
            //blink(volts);
         }           
       break;
       default:
           RobotSt(10);
        break;
      }
   }
 }