Robot Sound Chip

Updated 9/13/15

Key Search Words: PIC Microcontroller, CCS C Compiler, PIC Projects

 One of the biggest issues I encountered in writing the huge program for the Cbot plant watering robot is that I ran out of program memory before the project was completely finished. I had to cut and hack out large sections of essential code just to make the robot work at all. The problem was that the sensors drivers took tons of program ROM to implement, especially the compass. But the sound generation was also a large component, the beeps, whoops and chirps that are essential to know what the robot was thinking had to be cut back considerably. Can you imagine R2D2 from Star Wars without any sounds?

Here, I am putting every good sound I have ever made for a robot on one chip that is connected to a speaker, then simply sending a quick byte from the main processor to this chip via RS232 at 9600kb rate to make sounds. It takes all the bulky code OUT of the main processor and leaves it to do more important tasks. Also, once the sound command is sent, the main processor can continue to operate on other tasks even while the sound is still being generated.

Left: bench test setup of sound chip. The small board is the PIC16F628a generating the sounds, and the large board has the main processor, a 16F887 device. The transistor amp is above the speaker on the bread board.
Left: Schematic of sound chip with amp (click to enlarge)
Youtube video clip
I set the main processor to trigger all 13 sound effects separated by 2 seconds. You can hear all of them - turn your volume up!
Here is the code I have to send from the main processor:
 #use rs232(baud=9600, xmit=Pin_B2, bits=8, parity=N,STREAM=SOUND)

   s=2  //can be 1 - 13
   fputc(s,SOUND);
Here is the code (in CCS C) for the Sound Chip:
 //****************************************************************************
//Chris Schur
//(soundchp 16F628)
//Date:  9/7/15
//****************************************************************************
/*Description of this Program: 
This program sends out 13 different robot sounds via serial selection from another processor.
*/

//I/O Designations ---------------------------------------------------
// RA0:  
// RA1:  
// RA2:  
// RA3:  
// RA4:  (Open Collector output)
// RA5:  (MCLR)
// RA6:  Xtal  Output
// RA7:  Xtal  Input
// RB0:  SERIAL INPUT
// RB1:  
// RB2:  
// RB3:  SOUND OUT
// RB4:  
// RB5:  
// RB6:  
// RB7:  

//--------------------------------------------------------------------
//Include Files:
#include <16F628.h>  //Normally chip, math, etc.  used is here.
//Directives and Defines:
#fuses NOPROTECT,HS,NOWDT   //xtal is used
#use delay(crystal=10MHz)   //xtal speed
#use fast_io(ALL)          //must define tris below in main when using this
#use rs232(baud=9600, rcv=Pin_B0, bits=8, parity=N)
#define SPKR Pin_B3
//****************************************************************************
//Global Variables:
int16 n; //counting var
int16 d;  //sound delay var
int8 x;  //counting var
int8 sound = 0;  //selection for sound produced
//****************************************************************************
  
   
//Functions/Subroutines, Prototypes:
void beep1(void);  
void beep2(void);
void beep3(void);
void euro1(void);
void euro2(void);
void rampdn(void);
void rampup(void);
void tripplewhoop(void);
void siren(void);
void cricket(void);
void tripplecricket(void);
void twodutybeeps(void);
void twodutybeeps2(void);
//****************************************************************************
//-- Main Program
//****************************************************************************
void main(void) {
   // Set TRIS I/O directions, define analog inputs, compartors:
      set_tris_A(0b01111110);
      set_tris_B(0b11110001);
      
      //(analog inputs digital by default)  
   //Initialize variables and Outputs:  --------------------------------------
   
   output_low(SPKR);
   
   //Setup for timers, PWM, and other peripherals:
    
   //----------------------------------------------------------------
//MAIN LOOP:


while (true)   {
sound = getc();//select sound
  switch (sound) {
  
  case 0:
  
      output_low(SPKR);
      break;
      
  case 1:
      
      beep1();
      sound = 0;
      break;
  
  case 2:
  
      beep2();
      sound = 0;
      break;
  
  case 3:
  
      beep3();
      sound = 0;
      break;
  
  case 4:
  
      euro1();
      sound = 0;
      break;
  
  case 5:
  
      euro2();
      sound = 0;
      break;
  
  case 6:
  
      rampdn();
      sound = 0;
      break;
  
  case 7:
  
      rampup();
      sound = 0;
      break;
      
  case 8:
  
      tripplewhoop();
      sound = 0;
      break;
      
  case 9:
  
     siren();
     sound = 0;
     break;
     
  case 10:
  
      cricket();
      sound = 0;
      break;
      
  case 11:
  
      tripplecricket();
      sound = 0;
      break;
      
  case 12:
  
      twodutybeeps();
      sound = 0;
      break;
      
  case 13:
  
      twodutybeeps2();
      sound = 0;
      break;
  
    }  //switch
   
  }  //while
  
}  //main
//********* Functions which have prototypes at top of program ****************
//Beep 1:                     //Short single beep
void beep1(void)  {
   for(n=1; n<=50; n=n+1)  {
   output_high(SPKR);
   delay_ms(1);
   output_low(SPKR);
   delay_ms(1);
   }
   return; }  
   
   
//Beep2:                      //double beep
void beep2(void) {
beep1();  
delay_ms(50);
beep1();
return;  }

//Beep3:                       //Low tone beep
void beep3(void)  {
   for(n=1; n<=25; n=n+1)  {
   output_high(SPKR);
   delay_ms(2);
   output_low(SPKR);
   delay_ms(2); }
   return;  }
   
   
//Euro Beep1:                 //fast Two tone three times
void euro1(void)  {
   beep1();
   beep3();
   beep1();
   beep3();
   beep1();
   beep3();
   return;   }
   
   
//Euro Beep2:                  //standard slow beep
void euro2(void)  {
   for(n=1; n<=400; n=n+1)  {
   output_high(SPKR);
   delay_us(650);
   output_low(SPKR);
   delay_us(650);
   }
   
   for(n=1; n<=200; n=n+1)  {
   output_high(SPKR);
   delay_us(1200);
   output_low(SPKR);
   delay_us(1200); }
   
   for(n=1; n<=400; n=n+1)  {
   output_high(SPKR);
   delay_us(650);
   output_low(SPKR);
   delay_us(650);
   }
   
   for(n=1; n<=200; n=n+1)  {
   output_high(SPKR);
   delay_us(1200);
   output_low(SPKR);
   delay_us(1200); }
   
   for(n=1; n<=400; n=n+1)  {
   output_high(SPKR);
   delay_us(650);
   output_low(SPKR);
   delay_us(650);
   }
   
   for(n=1; n<=200; n=n+1)  {
   output_high(SPKR);
   delay_us(1200);
   output_low(SPKR);
   delay_us(1200); }
   
   return;   }
   
   
//Ramping tones -----------------------------
void rampdn(void)  {    //high tone to low ramp
d=1500;
for(n=1; n<=500; n=n+1)  {
   output_high(SPKR);
   delay_us(d);
   output_low(SPKR);
   delay_us(d);
   d++;   }
   
   return;   }
   
   
   
void rampup(void)  {     //low tone to high ramp
d=1500;
for(n=1; n<=500; n=n+1)  {
   output_high(SPKR);
   delay_us(d);
   output_low(SPKR);
   delay_us(d);
   d--;   }
   
   return;   }
   
   
void tripplewhoop(void)  {  //go  1200 to 600 us
  for(x=1; x<=3; x++)  {
   
   d=1200;
   
   for(n=1; n<=200; n=n+1)  {
   output_high(SPKR);
   delay_us(d);
   output_low(SPKR);
   delay_us(d);
   d = d-3; 
    }
    
    delay_ms(100);
   
  }
   
   return;   }
   
   
void siren(void)  {  //sort of a sick sounding up down wail
   rampup();
   rampdn();
}
//  CREATURE SOUNDS:
void cricket(void)   {  //single chirp


for (x=0; x<=10; x++)  {
      output_high(SPKR);
      delay_us(250);
      output_low(SPKR);
      delay_us(250);    }
      
      delay_ms(20);
      
      for (x=0; x<=10; x++)  {
      output_high(SPKR);
      delay_us(312);
      output_low(SPKR);
      delay_us(312);    }
      
      delay_ms(20);
      
for (x=0; x<=10; x++)  {
      output_high(SPKR);
      delay_us(312);
      output_low(SPKR);
      delay_us(312);    }
      
      delay_ms(20);
      
for (x=0; x<=10; x++)  {
      output_high(SPKR);
      delay_us(312);
      output_low(SPKR);
      delay_us(312);    }
      
      delay_ms(20);
      
for (x=0; x<=10; x++)  {
      output_high(SPKR);
      delay_us(312);
      output_low(SPKR);
      delay_us(312);    }
      
      delay_ms(20);
   
}

void tripplecricket(void)  {
cricket();
delay_ms(600);
cricket();
delay_ms(600);
cricket();  }


void twodutybeeps(void)  {   //1 khz beeps
//first beep 50% duty:
for(n=1; n<=100; n=n+1)  {
   output_high(SPKR);
   delay_us(500);
   output_low(SPKR);
   delay_us(500);  }
   
//second beep 10% duty:
for(n=1; n<=100; n=n+1)  {
   output_high(SPKR);
   delay_us(25);
   output_low(SPKR);
   delay_us(975);  }
}
void twodutybeeps2(void)  {   //1 khz beeps
//first beep 50% duty:
for(n=1; n<=200; n=n+1)  {
   output_high(SPKR);
   delay_us(250);
   output_low(SPKR);
   delay_us(250);  }
   
//second beep 10% duty:
for(n=1; n<=200; n=n+1)  {
   output_high(SPKR);
   delay_us(25);
   output_low(SPKR);
   delay_us(475);  }
}
HOME