Cylon Pumpkin

I realize (now) this has been done to death but I've never been able to let go of a bad idea once I get it in my head. So, a Cylon pumpkin. The goals are: the sweeping cylon eye, the cylon noise, motion sensing.

My proof of concept uses a parallax pir motion sensor, a string of 20X2 LEDs for the eye display, and the speaker_pcm code by Michel Smith from the playground driving a powered speaker. I have it hooked up to do a slow cylon scan in silence with no motion then speed up and start the sound when it senses motion.

Some things work well: it doesn't see motion at the street but it easily sees you as you come up the walk way and the cylon sound effect is pretty darned good(despite what my wife says after putting up with my testing).

The led array is a disappointment though - not at all cylonic or menacing. I got some brighter leds which I will hook up in a single row - I don't know why I thought the double row was a good idea.

It really does look sad held on with duct tape. It's like the cylon nerd with his glasses held together with tape. In the final product the leds will be inside an eye slit of course.

Anyway, I've already learned more than I wanted to know about several subjects and I've still got two weeks to abuse this poor gourd.

ref:
Parked at Loopia The scanning eye sound
http://web.me.com/shayman/Nothing_Really/Cylon_Pumpkin.html A very pretty effort from halloween 2008 - no sound or motion detection though
Arduino Playground - PCMAudio the pcm audio code on the playground

oh, oh, I forgot. The final version will use bluetooth to signal my PC inside the house that we have a visitor.

my pumpkin is very very ugly.

But it does have a mullet.

Hey, would you be willing to share your code & a pic of your circuit? It might be a little much for me on the hardware side, but I'd like to take a look anyway :slight_smile:

Where do you buy parts in Ottawa?

Hey, would you be willing to share your code & a pic of your circuit? It might be a little much for me on the hardware side, but I'd like to take a look anyway

Where do you buy parts in Ottawa?

Best local sources of parts that I know of are:Gervais Electronics on Industrial near St Laurent, and Active Components on Merivale. Both have walk-in retail with stands of resistors, connectors, and the like and a catalog of components backing them up. For ordering-in I find digikey.ca to be best, $8 flat fee shipping, no customs hassles, and very quick.

Here's a few pics of the Cylon Pumpkin's hardware and the code. Happy to help with any questions.


//version 2 of the cylon pumpkin.
//incorporates wav player with soft playback option
//plays cylon noise at low volume til motion is detected.
//starts cylon noise as soon as motion is detected rather than at beginning of scan
//waveform modified to reduce pop at beginning of playback
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>

#define SAMPLE_RATE 8000

//Charlieplexing a cylon pumpkin display
const int cpin1=4;   //Charlieplexing pin 1 
const int cpin2=5;  //Charlieplexing pin 2 
const int cpin3=6; //Charlieplexing pin 3  
const int cpin4=7;  //Charlieplexing pin 4 
const int cpin5=8; //Charlieplexing pin 5
const int cpin6=9; //Charlieplexing pin 5

int clow=1; 
int chigh=25; //low and high scan limits
int s1=clow; 
int delta=1; //scan start, direction
int csfast=50; 
int csslow=200;   //fast and slow scans
int pirpin=3; 
int ledpin=13; //pins for motion detector and standalone led

#include "sounddata.h"


int speakerPin = 11;
volatile uint16_t sample;
byte lastSample;
boolean softly=true; 

void setup() {
  Serial.begin(9600);
  pinMode(ledpin,OUTPUT);
  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
  for(int i = 1; i <= 25; i++){
    cplex(i);
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  delay(50);
  startPlayback();

}

void loop(){
  static boolean excited=false; //excited is true when motion is detected
  int csspd=csslow; //by default eye scan is slow
  if(digitalRead(pirpin)==HIGH){
    csspd=csfast;
    digitalWrite(ledpin,HIGH); 
    if (!excited){
      softly=false; 
      startPlayback();
      excited=true;
    } 
  }
  else {
    csspd=csslow; 
    excited=false; 
    softly=true; 
    digitalWrite(ledpin,LOW); 
  }
  int s2=s1+delta; //inner scan
  cplex2(s2,s1,csspd); //cplex 2 positions
  s1=s1+delta;
  if (s1>=chigh){
    s1=chigh-1;
    delta=-1;
  }
  if (s1<=clow){
    s1=clow+1;
    delta=1;
    startPlayback();
  }
}

void cplex2(int which,int which2, int t){ //cplex 2 positions for t ms
  unsigned long when=millis()+t; //when to stop
  while(millis()<when){
    Serial.print(" t=");
    Serial.println(t);
    cplex(which); 
    delay(2);
    cplex(which2); 
    delay(2);
  }
}

void cplex(byte digit){ 
  pinMode(cpin1,INPUT);   
  pinMode(cpin2,INPUT); 
  pinMode(cpin3,INPUT);
  pinMode(cpin4,INPUT);
  pinMode(cpin5,INPUT);
  pinMode(cpin6,INPUT);//safe mode
  digitalWrite(cpin1,LOW);  
  digitalWrite(cpin2,LOW);  
  digitalWrite(cpin3,LOW);  
  digitalWrite(cpin4,LOW);  
  digitalWrite(cpin5,LOW);  
  digitalWrite(cpin6,LOW);
  int cpinh[]={
    cpin1, //0 isn't used
    cpin1,cpin2,cpin1,cpin3,cpin1, //1-5
    cpin4,cpin1,cpin5,cpin1,cpin6, //6-10
    cpin5,cpin6,cpin4,cpin6,cpin3, //11-15
    cpin6,cpin2,cpin6,cpin2,cpin5, //16-20
    cpin2,cpin4,cpin2,cpin3,cpin4  }; //21-25
  int cpinl[]={
    cpin1, //0 isn't used
    cpin2,cpin1,cpin3,cpin1,cpin4,
    cpin1,cpin5,cpin1,cpin6,cpin1,
    cpin6,cpin5,cpin6,cpin4,cpin6,
    cpin3,cpin6,cpin2,cpin5,cpin2,
    cpin4,cpin2,cpin3,cpin2,cpin3  };
  pinMode(cpinh[digit],OUTPUT); 
  digitalWrite(cpinh[digit],HIGH);
  pinMode(cpinl[digit],OUTPUT); 
  digitalWrite(cpinl[digit],LOW);
}
// This is called at 8000 Hz to load the next sample.
ISR(TIMER1_COMPA_vect) {
  if (sample >= sounddata_length) {
    if (sample == sounddata_length + lastSample) {
      stopPlayback();
    }
    else {
      // Ramp down to zero to reduce the click at the end of playback.
      OCR2A = sounddata_length + lastSample - sample;
    }
  }
  else {
    if(softly){
      OCR2A = pgm_read_byte(&sounddata_data[sample])>>2;
    } //reduce volume of playback
    else{
      OCR2A = pgm_read_byte(&sounddata_data[sample]); //full volume playback
    }
  }

  ++sample;
}

void startPlayback()
{
  pinMode(speakerPin, OUTPUT);

  // Set up Timer 2 to do pulse width modulation on the speaker
  // pin.

  // Use internal clock (datasheet p.160)
  ASSR &= ~(_BV(EXCLK) | _BV(AS2));

  // Set fast PWM mode  (p.157)
  TCCR2A |= _BV(WGM21) | _BV(WGM20);
  TCCR2B &= ~_BV(WGM22);

  // Do non-inverting PWM on pin OC2A (p.155)
  // On the Arduino this is pin 11.
  TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
  TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));

  // No prescaler (p.158)
  TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

  // Set initial pulse width to the first sample.
  if (softly) 
    OCR2A = pgm_read_byte(&sounddata_data[0])>>2;
  else
    OCR2A = pgm_read_byte(&sounddata_data[0]);



  // Set up Timer 1 to send a sample every interrupt.

  cli();

  // Set CTC mode (Clear Timer on Compare Match) (p.133)
  // Have to set OCR1A *after*, otherwise it gets reset to 0!
  TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
  TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));

  // No prescaler (p.134)
  TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);

  // Set the compare register (OCR1A).
  // OCR1A is a 16-bit register, so we have to do this with
  // interrupts disabled to be safe.
  OCR1A = F_CPU / SAMPLE_RATE;    // 16e6 / 8000 = 2000

  // Enable interrupt when TCNT1 == OCR1A (p.136)
  TIMSK1 |= _BV(OCIE1A);

  lastSample = pgm_read_byte(&sounddata_data[sounddata_length-1]);
  if (softly) lastSample=lastSample>>2;
  sample = 0;
  sei();
}

void stopPlayback()
{
  // Disable playback per-sample interrupt.
  TIMSK1 &= ~_BV(OCIE1A);

  // Disable the per-sample timer completely.
  TCCR1B &= ~_BV(CS10);

  // Disable the PWM timer.
  TCCR2B &= ~_BV(CS10);

  digitalWrite(speakerPin, LOW);
}

Bwahahahaha I love it! Maybe you could get it to play Cylon voice samples like "By your command"?

Any chance of you posting a schematic? I'm having a little trouble figuring out the circuit on the breadboard.

kool gonna make up a schematic for it? :3

I'm having a little trouble figuring out the circuit on the breadboard.

not surprising - I'm looking at that cluster of orange yellow and green wires in the middle and they are left over from a test rig - not connected to anything! I'll see if I can make a simple schematic.
Here's a more readable layout from fritzing. The parts are not identical but they're in roughly the same spots on the board.

Also, a little duct tape has helped appearance-wise. The "earring" on the right is the motion-detector (aka targeting radar).

The cylon pumpkin was a huge hit with the trick-or-treat crowd. As my daughter's boyfriend said "Electricity makes everything better".

Terribly crufty code but it's amazing what you can put together by cribbing other people's work.