I’ve gotten a few questions about the PIR sensor enclosures I use. My sensor of choice is the SR602 it accepts a supply of 3.3-18 V and outputs HIGH (3.3V) for 2 seconds when movement is sensed. The form factor is the real reason I prefer it, though. The circuit board for the SR602 is circular and fits perfectly inside a 1/2” PVC fitting.
Jekyll Labs Projects
Wednesday, August 16, 2023
Friday, April 28, 2023
How to Program a Twitch-n-Howl Board
Both Sparkfun and Arduino.cc have great tutorials on this subject (most of these pictures below are taken from these sites). Links are at the bottom.
If you can program an Arduino, you can program a Twitch-n-Howl board. That's because both boards use the same ATmega328 chip to store and execute code. In order to save space, the Twitch-n-Howl board does not have a USB port. In order to upload code, you will need to set up a dedicated Arduino as a "Programmer" and connect that Arduino to the ISP header of the Twitch-n-Howl.
First connect your "Programmer" board to your computer and upload the ArduinoISP.ino file. This is located in the Examples in the File menu. Upload this just like any other sketch.
Now you can connect your programmer board (I'm using a Sparkfun Redboard Arduino Uno clone here) to the Twitch-n-Howl. I like using a clip with pogo pins (like this one), but you could also solder a pin header to the board and just use jumpers.
**On these links you'll see instructions for loading the bootloader onto a new ATmega328 chip. This will be unnecessary for the Twitch-n-Howl board as it has already been done at Jekyll-Labs. **
Sunday, April 23, 2023
Twitchboard v1.7 Code and Schematics
// Jekyll-Labs Twitchy Attiny85
// Built for Twitchboard v1.7
//
// Pin definitions
int fetpin = 0;
int trigpin = 3;
int potpin = A2;
// global variables
long duration = 200; // duration in miliseconds (200)
long PWM = 255; // Duty cycle 0-255 (255)
long intervallow = 2000; // low end of interval range in sec [2 sec]
long intervalmid = 10000; // middle of interval range in sec [10sec]
long intervalhigh = 90000; // high end of interval range in sec [90sec]
long intervalmax = 36000000; // interval in sec if pot maxed out [10hrs]
// initialize global variables
long timeunit = 0;
unsigned long last = 0;
unsigned long timeinterval = 0;
float exprob=0.50;
void setup() {
randomSeed(A1);
pinMode(fetpin, OUTPUT);
digitalWrite(fetpin, LOW);
pinMode(trigpin, INPUT);
pinMode(potpin, INPUT);
}
void loop() {
// uncomment if pot controls duration
// duration of signal will last from 0.5 - 10 sec
//int durationpot = analogRead(potpin);
//long duration = map(durationpot,100,1023,500,10000);
//if (duration <500) duration = 150;
// uncomment if pot controls PWM
// read middle pot for PWM of fet signal
//int PWMpot = analogRead(potpin);
//int PWM = map(PWMpot,0,1000,0,255);
//if (PWM>255) PWM = 255;
// uncomment if pot controls frequency
// mean frequency of random signals is 1 events per time unit
int freqpot = analogRead(potpin);
long timeunit = map(freqpot,512,1023,intervalmid,intervalhigh); // 2nd half dial range
if (freqpot>1000) timeunit = intervalmax; // far right dial 1hr
if (freqpot<512) timeunit = map(freqpot,0,512,intervallow,intervalmid); // 1st half dial range
if (freqpot<100) timeunit = 0; // bottom of dial continous on
if (timeunit<=0){ // continuous on if left dial all counter clockwise
analogWrite(fetpin,PWM);
}
else {
// Check for trigger (X3 for debounce) and adjust
// timeunit if trigger is positive.
if (timeunit>0) {
int trigger = digitalRead(trigpin);
if (trigger == HIGH) {
delay(100);
int trigger = digitalRead(trigpin);
if (trigger == HIGH) {
delay (100);
int trigger = digitalRead(trigpin);
if (trigger == HIGH) {
timeunit = (duration * 2);
}
}
}
}
// Calcuate time interval between events. timeunit depends on:
// Potentiometer value if trig = 0
// Duration multiplier (shorter) if trig = 1
unsigned long timeinterval = exprob * timeunit;
// Check if time interval has passed
if ((millis() - last) > timeinterval) {
last = millis(); // updates timer to last event
analogWrite(fetpin,PWM);
long duration = random(2000)+3000;
delay(duration);
digitalWrite(fetpin,LOW);
// the following equation runs once per event and
// generates a random float (exprob) that falls in an
// exponential distribution. It will be used to
// determine the interval time for the next event.
// Events that occur at exponentially distributed
// intervals form poisson processes.
exprob = (-2)*(log((100-random(100))/100.00));
}
else digitalWrite(fetpin,LOW);
}
delay(20);
}
Sunday, April 16, 2023
Twitch-n-howl Code and Schematics v2.2
Code:
// Jekyll-Labs Twitch and Sound
// Built for Twitchnhowl v2.2
//
// D2 unused
// D3 Power MOSFET (PWM avail)
// D4 unused
// D5 On Board LED1
// D6 On Board LED2
// D7 SoftSerial Tx
// D8 SoftSerial Rx
// D9 Trigger Input
// D10 unused
// D11 MOSI
// D12 MISO
// D13 SCK
// A0/D14 unused
// A1/D15 unused
// A2/D16 unused
// A3/D17 Potentiometer Top
// A4/D18 Potentiometer Middle
// A5/D19 Potentiometer Bottom
// A6/D20 unused
// A7/D21 unused
//include libraries
#include "Arduino.h"
#include "SoftwareSerial.h"
// set pin identification
int fetpin = 3;
int trigpin = 9;
int led1 = 5;
int led2 = 6;
int potMpin = A4;
int potTpin = A3;
int potBpin = A5;
//set SoftSerial for JQ8900 and basic Hex commands
SoftwareSerial mySoftwareSerial(8, 7); // RX, TX
byte playnext[] = {0xAA, 0x06, 0x00, 0xB0 };
// set global constants
unsigned long durationlow = 200; // low end of duration range in msec [0.2sec]
unsigned long durationhigh = 15000; // high end of duration range in msec [15sec]
long intervallow = 2000; // low end of interval range in sec [2 sec]
long intervalmid = 10000; // middle of interval range in sec [10sec]
long intervalhigh = 90000; // high end of interval range in sec [90sec]
long intervalmax = 36000000; // interval in sec if pot maxed out [10hrs]
unsigned long mosfetdelay = 0; // extra delay to turn mosfet on after audio triggered [0]
// initialize global variables
long timeunit = 12; // mean untriggered time interval (sec)
unsigned long last = 0;
unsigned long timeinterval = 0;
float exprob=0.50;
void setup() {
// setup mosfet pin as output
pinMode(fetpin, OUTPUT);
digitalWrite(fetpin, LOW);
// set up potentiometers and trigger pin
pinMode(trigpin, INPUT);
pinMode(potTpin, INPUT);
pinMode(potMpin, INPUT);
pinMode(potBpin, INPUT);
// Set up and turn off LED
pinMode(led1, OUTPUT);
digitalWrite(led1, LOW);
pinMode(led2, OUTPUT);
digitalWrite(led2, LOW);
// begin softserial for JQ8900
mySoftwareSerial.begin(9600);
last = millis(); // updates timer to start
randomSeed(A0);
}
void loop() {
// duration of signal will last from 0.5 - 10 sec
int durationpot = analogRead(potBpin);
long duration = map(durationpot,100,1023,durationlow,durationhigh);
if (duration <500) duration = 150;
// read middle pot for PWM of fet signal
int PWMpot = analogRead(potMpin);
int PWM = map(PWMpot,0,1000,0,255);
if (PWM>255) PWM = 255;
// mean frequency of random signals is 1 events per timeunit
int intervalpot = analogRead(potTpin);
long timeunit = map(intervalpot,512,1023,intervalmid,intervalhigh); // 2nd half dial range 12-60 sec
if (intervalpot>1000) timeunit = intervalmax; // far right dial 1hr
if (intervalpot<512) timeunit = map(intervalpot,75,512,intervallow,intervalmid); // 1st half dial range 0-12 sec
if (intervalpot<75) timeunit = 0; // bottom of dial continous on
if (timeunit<=0){ // continuous on if left dial all counter clockwise
analogWrite(fetpin,PWM);
digitalWrite(led2,HIGH);
}
else {
// Check for trigger (X3 for debounce) and adjust
// timeunit if trigger is positive.
if (timeunit>0) {
int trigger = digitalRead(trigpin);
if (trigger == HIGH) {
delay(100);
int trigger = digitalRead(trigpin);
if (trigger == HIGH) {
delay (100);
int trigger = digitalRead(trigpin);
if (trigger == HIGH) {
timeunit = 2000; // minimum mean interval in sec for triggered events
digitalWrite(led1,HIGH);
}
}
}
if (trigger == LOW) digitalWrite(led1,LOW);
}
// Calcuate time interval between events. timeunit depends on:
// Potentiometer value if trig = 0 (not triggered)
// Duration multiplier (shorter) if trig = 1
unsigned long timeinterval = exprob * timeunit;
// Check if time interval has passed and if so trigger event
if ((millis() - last) > timeinterval) {
last = millis(); // updates timer to last event
digitalWrite(led2,HIGH); // indicator LED
mySoftwareSerial.write(playnext, sizeof(playnext)); // play next MP3
delay(10);
if (random(2)<1) mySoftwareSerial.write(playnext, sizeof(playnext)); // 50% of the time skip to next MP3
delay(100 + mosfetdelay);
analogWrite(fetpin,PWM); // turn on mosfet
delay(duration);
digitalWrite(fetpin,LOW);
digitalWrite(led2,LOW);
// the following equation runs once per event and
// generates a random float (exprob) that falls in an
// exponential distribution. It will be used to
// determine the interval time for the next event.
// Events that occur at exponentially distributed
// intervals form poisson processes.
exprob = (-2)*(log((100-random(100))/100.00));
}
else {
digitalWrite(fetpin,LOW);
digitalWrite(led2,LOW);
}
}
delay(20);
}
Saturday, March 11, 2023
Generating a Poisson Process from Uniformly Distributed Pseudo-random Numbers
Most microprocessors generate pseudorandom numbers that follow a uniform distribution. This is great for simulating things like rolling dice where the probability of rolling a 1 is the same as rolling a 4. It turns out, however, that for most natural processes, the time between events is more accurately modeled using an exponential distribution of random numbers. This results in both more clustering of events and larger gaps in between them. These are called poisson processes because the distribution of events-per-time-interval follow a Poisson distribution.
In both of the two samples below, there are twenty events per time interval. In the first sample, events are spaced using a uniform distribution of random numbers. In the second sample, events are spaced using an approximate exponential distribution (thereby generating a Poisson process).
This default code for the Twitch-n-Howl board uses a mathematical transformation to convert the uniformly distributed pseudorandom numbers into exponentially distributed numbers.
This same transformation is depicted graphically below. The blue line shows a uniform distribution of random numbers, while the red line shows an exponential distribution of random numbers. Both distributions have the same mean and area under the curve.
These exponentially distributed random numbers are used to determine spacing between events. One can see that using an exponential distribution of random numbers to determine event spacing would result in some events closer together and some events further apart than would be present using a uniform distribution of random numbers for event spacing. This is one of the properties of a Poisson process and helps explain why natural random events seem so unpredictable.
Friday, March 3, 2023
Flicker LED Amplifier
Most of these LEDs have a small integrated circuit embedded in the plastic head that can seen if you look closely.
There’s a great discussion of reverse engineering these flicker LEDs in Tim’s Blog post “Hacking a Candleflicker LED”. He uses a logic analyzer to look at current drawn by the flicker LED. This reveals what appears to be a PWM signal of varying intensity that controls the flicker effect.
He then goes on a really impressive deep dive quantifying the PWM levels and speculating on the pseudorandom sequence generation. —Go read it, seriously. It’s not long and really fascinating.—
Windell Oskay, over at Evil Mad Scientist, put together a great post "Does this LED sound funny to you?" in which he uses a PNP transistor to amplify the signal being drawn by the flicker LED. he then sends this to a LED and then a speaker. Unfortunately the STX790a transistor he selects has been discontinued, and I had some difficulty finding a similar spec’d transistor (ie stopped after 10 minutes of google-ing). I did have some PN2907 PNP transistors lying around. I tried one of those in Oskay’s circuit.
The flicker LED would flicker nicely, but unfortunately just caused the transistor to continuously conduct. The secondary LED would just stay lit, perhaps a bit dimmer than usual. Interestingly enough, when I hooked the transistor up backwards (still in the same place in the circuit, but just swapping the collector and the emitter leads) both the flicker LED and the secondary LED would flicker. The effect seemed stable. The transistor was still working as a PNP transistor, but just with unknown specs. Seemed kind of sketchy and not exactly something I could recommend to others… So back to my parts box…
I have several "logic-level" N-channel mosfets lying around in my parts box, specifically the IRLB8721 and the FQP30N06L. I use both of these frequently for rapid switching (PWM and otherwise) up to a few amps of current at 12V.
I set up my mini digital oscilloscope to query the voltage at a few points along a simple flicker LED circuit and found that I could reliably detect the signal between the LED and the resistor when they were arranged like this.
Friday, December 30, 2022
JQ8900-16p MP3 player
(1) There is a two-way serial connection using the Rx and Tx pins. This is the most robust way with many options analogous to the DFPlayer serial connection. Unfortunately, the serial commands are different from the DFPlayer, and I'm not aware of an existing Arduino library. Fortunately, the JQ8900 seems to be based on the JQ8400. The JQ8400 does have an Arduino library, but I have not personally used it. Both the JQ8900 and the JQ8400 have manuals that have been translated into English and have good information.
With the JQ8900, I'm partial to using the serial commands directly. "AA 06 00 B0" will play the next file. I've included below some example code that will every 5 seconds play the next file in sequence.
(2) There is a single wire input mode available using the VPP pin. I haven't personally used this, but there are many examples online (unfortunately for me, mostly in Chinese)
(3) The JQ8900 has 7 trigger pins. These are great. When the IO1 pin is connected to ground the JQ8900 will play the file named 00001.mp3 (and so on). This works well for manual buttons as well as microcontrollers. With this board, I used an ATTINY85 sending a signal to an NPN transistor to connect IO1 to ground.
Audio output is either speaker output (appears to be a 3W amplifier) or line level output via DAC and ground. For both outputs, the JQ8900 collapses the right and left channels into a single mono channel. This is a disadvantage as compared to the DFPlayer, which has mono output for the speaker, but stereo ouput for line level. If you need stereo output, the JQ8900 may not be the board for you.
Links
JQ8900 Manual - English version
JQ8400 Manual - English version
excellent collection of links [Chinese] The JQ8900-16P voice module hardware usage _ Lin Zhong Qiyuan's blog - CSDN blog _jq8900
//include libraries
#include "Arduino.h"
#include "SoftwareSerial.h"
SoftwareSerial mySoftwareSerial(15, 14); // RX, TX
void setup(){
randomSeed(analogRead(0));
delay(1000);
mySoftwareSerial.begin(9600);
pinMode(4, INPUT);
}
void loop()
{
byte playnext[] = {0xAA, 0x06, 0x00, 0xB0 };
int trig = digitalRead(4);
if (trig == HIGH) {
mySoftwareSerial.write(playnext, sizeof(playnext));
delay(5000);
}
delay(100);
}
Monday, December 5, 2022
Twitchboard
Previously I worked on a motor controller board that would deliver random pulses to a prop. It worked well, but I was not quite happy with the randomization algorithm, and I wanted more titratable control over the pulses. Additionally I wanted something that could be triggered by either a PIR sensor or a button.
I’ve now produced a beta version of this new controller and I’m looking for feedback. Here’s a demo video—
This is the schematic—
And here is the code—
// Jekyll-Labs Twitchy Attiny85 // Built for Twitchboard v1.5 // int fetpin = 0; int trigpin = 1; int potMpin = A1; int potRpin = A2; int potLpin = A3; int lambda = 5; // number of event int timeunit = 60; // in this time interval (sec) unsigned long last = 0; unsigned long timeinterval = 0; float exprob=0; void setup() { randomSeed(A1); pinMode(fetpin, OUTPUT); digitalWrite(fetpin, LOW); pinMode(trigpin, INPUT); pinMode(potLpin, INPUT); pinMode(potMpin, INPUT); pinMode(potRpin, INPUT); } void loop() { // duration of signal will last from 0.5 - 10 sec int durationpot = analogRead(potRpin); long duration = map(durationpot,100,1023,500,10000); if (duration <500) duration = 150; // read middle pot for PWM of fet signal int PWMpot = analogRead(potMpin); int PWM = map(PWMpot,0,1000,0,255); if (PWM>255) PWM = 255; // mean frequency of random signals is 5 events per time unit int freqpot = analogRead(potLpin); int timeunit = map(freqpot,512,1023,60,300); // 2nd half dial range 1-5 min if (freqpot>1000) timeunit = 3600; // far right dial 1hr if (freqpot<512) timeunit = map(freqpot,0,512,0,60); // 1st half dial range 10-60 sec if (freqpot<100) timeunit = 0; // bottom of dial continous on if (timeunit<=0){ // continuous on if left dial all counter clockwise analogWrite(fetpin,PWM); } else { // Check for trigger (X3 for debounce) and adjust // timeunit if trigger is positive. if (timeunit>0) { int trigger = digitalRead(trigpin); if (trigger == HIGH) { delay(100); int trigger = digitalRead(trigpin); if (trigger == HIGH) { delay (100); int trigger = digitalRead(trigpin); if (trigger == HIGH) { timeunit = (duration * 10)/1000; } } } } // Calcuate time interval between events. timeunit depends on: // Potentiometer value if trig = 0 // Duration multiplier (shorter) if trig = 1 unsigned long timeinterval = exprob * timeunit * 1000; // Check if time interval has passed if ((millis() - last) > timeinterval) { last = millis(); // updates timer to last event analogWrite(fetpin,PWM); delay(duration); digitalWrite(fetpin,LOW); // the following equation runs once per event and // generates a random float (exprob) that falls in an // exponential distribution. It will be used to // determine the interval time for the next event. // Events that occur at exponentially distributed // intervals form poisson processes. exprob = (-1)*(log((100-random(100))/100.00)/lambda); } else digitalWrite(fetpin,LOW); } delay(20); }
Thursday, August 18, 2022
Lightboard
**Updates Log**
9/27/22 code updated for millis() rollover
2/3/23 parts list included
So I’m, really happy about this new board I had made.
It uses a Arduino Nano to control PWM signals for six different channels of lights. There are two potentiometers, one to select the effect, and a second to change the speed of that effect. The board uses IRLB8721 mosfets to control current to the lights. According to Adafruit these mosfets are capable of switching 15A of current so each channel could run several lights in parallel.
These are the lights I use. They were suggested by another haunter, because they are waterproof, they fit inside a PVC fitting, and draw only 60mA at 12V DC. To find them you can search Eagle Eye LED 18mm on Amazon/EBay/AliExpress.
Here’s a 4 minute demo of the board in the lab:
There are 4 different effects:
1. Solid - all lights are on and dimmable by the speed potentiometer
2. Firelight - a low flicker meant to evoke the light of a fire. Works well with several amber on the same channel and 1 dim red on another channel
3. Wavey - All channels slowly pulse on and off at slightly different wavelengths so they don’t synchronize. Speed potentiometer controls how fast they pulse
4. Lightning - Each channel strobes on with a random delay and a random number of flashes. Speed potentiometer controls how frequent the flashes are.
**I'm not in the business of selling Halloween circuit boards, but I usually have to order more than I need for any given project. If you're into DIY electronics (and let's face it, you wouldn't be reading this otherwise), and want one of my boards, send me a PM.**
Here's the Fritzing:
Here's the code for the nano: (updated 9-27-22 to fix millis() rollover.)
// Jekyll-Labs Lightboard v1.0
// D2 sensor
// D3 Power MOSFET (PWM avail)
// D4 sensor
// D5 Power MOSFET (PWM avail)
// D6 Power MOSFET (PWM avail)
// D7 Unused
// D8 Unused
// D9 Power MOSFET (PWM avail)
// D10 Power MOSFET (PWM avail)
// D11 Power MOSFET (PWM avail)
// D12 unused
// D13 unused
// A0/D14 Unused
// A1/D15 10k potentiometer
// A2/D16 10k potentiometer
// A3/D17 Unused
// A4/D18 Unused
// A5/D19 Unused
// A6/D20 Unused
// A7/D21 Unused
int ledpin[] = {3, 5, 6, 9, 10, 11};
int effectpin = A1;
int freqpin = A2;
int effect = 0;
int freq = 0;
int brightness[6];
int oldbrightness[6];
int fldelay = 75; // fire light flicker delay
int flalpha = 20; // fire light alpha 0-100 (low values less dynamic changes)
unsigned long lastupdate[6];
int between=500;
int randwavel[6];
int wavelength[6];
void setup() {
Serial.begin(9600);
randomSeed(A0);
for (int i =0; i<=5; i++) {
pinMode(ledpin[i],OUTPUT);
digitalWrite(ledpin[i],LOW);
}
for (int i =0; i<=5; i++) { //setting variables for flicker
brightness[i]= random(256);
oldbrightness[i] = brightness[i];
randwavel[i] = random(500);
}
}
void firelight(){
for (int i =0; i<=5; i++) {
if ((millis()-lastupdate[i])>fldelay) {
lastupdate[i] = millis();
brightness[i] = random(255);
brightness[i] = (flalpha * brightness[i] + (100 - flalpha)*oldbrightness[i])/100;
oldbrightness[i] = brightness[i];
analogWrite(ledpin[i],brightness[i]);
}
}
}
void wavey(){
for (int i =0; i<=5; i++) {
wavelength[i] = (freq/100)*1500 +1000 + randwavel[i];
int remainder = millis() % wavelength[i];
if (remainder <wavelength[i]/2){
brightness[i] = map(remainder, 0, wavelength[i]/2,-128,384);
if (brightness[i]<0) brightness[i]=0;
if (brightness[i]>255) brightness[i]=255;
}
if (remainder >=wavelength[i]/2) {
brightness[i] = map(remainder,wavelength[i]/2,wavelength[i],384,-128);
if (brightness[i]<0) brightness[i]=0;
if (brightness[i]>255) brightness[i]=255;
}
analogWrite(ledpin[i],brightness[i]);
}
}
void solid(){
freq = map(freq,100,923,0,255);
if (freq<0) freq=0;
if (freq>255) freq=255;
for (int i =0; i<=5; i++) {
analogWrite(ledpin[i],freq);
}
}
void lightning(){
for (int i =0; i<=5; i++) {
if ((millis() - lastupdate[i])> between) {
for (int c=0; c< random(7); c++){
digitalWrite(ledpin[i], HIGH);
delay(40);
digitalWrite(ledpin[i], LOW);
delay(10);
}
int lidelay = map(freq,0,1023,3000,20000);
between = 500+ random(lidelay);
lastupdate[i] = millis();
}
}
}
void loop() {
freq = analogRead(freqpin);
effect = analogRead(effectpin);
if (effect<100) solid();
if ((effect>=100)&(effect<512)) firelight();
if ((effect>=512)&(effect<923)) wavey();
if (effect>=923) lightning();
delay(10);
}
Parts List and links
Wednesday, August 17, 2022
Fake Electric Zap (capacitive touch)
Friday, July 1, 2022
Spider Victim with Random Twitching Movement
I wanted to show off a twitching victim I made for a friend's spider themed haunt. Here's a video of the prop in action.
The mechanism is based on an automatic car door lock motor like this:
It's available on Amazon for about $6 and runs on 12v DC. Here are a couple close up pictures of the mechanics.
The PVC and motor were then covered with plastic bags for bulk and then a couple layers of plastic treated with a heat gun to give the right corpsed/spun web appearance.
This electronics for this project are an extension of a lighting simulator I made previously. For this project, the frequency of the random twitches are controlled by the potentiometer. The arduino sends 5 volt signals to the mosfet which in turn controls the 12 volt motor.
To keep things small and cheap, I built the circuit based around an ATTINY85. These processors are great because they are very cheap (usually <$2) and programmable using the Arduino IDE. Here's a picture of the board.
Alternatively this could be built with an arduino uno and mosfet as a simple first arduino project.
Here's the schematic for the circuit:
And here's the code: [code updated 8/29/22 to account for millis() rollover]
// Jekyll-Labs Twitchy Att
iny85
// Built for Randflash board v1.1
//
int fet = 0;
int pulses = 1;
int pot = A1;
unsigned long start = 0;
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(fet, OUTPUT);
randomSeed(A0);
}
// the loop function runs over and over again forever
void loop() {
int potsens = analogRead(pot);
if (potsens < 120) potsens = 0;
unsigned long delaybonus = map(potsens,0,1023,0,600000);
if ((millis() - start)>(3000 + delaybonus)){
start = millis();
pulses = random(3)+1;
for (int i = 0; i < pulses; i++) {
digitalWrite(fet, HIGH); // turn the LED on (HIGH is the voltage level)
delay(150); // wait for a second
digitalWrite(fet, LOW); // turn the LED off by making the voltage LOW
delay(600); // wait for a second
}
}
else {
digitalWrite(fet,LOW);
}
delay(10);
}
Wednesday, June 22, 2022
Lightning Simulator
//
// FILE: lightning.pde
// AUTHOR: Rob Tillaart
// DATE: 2012-05-08
//
// PUPROSE: simulate lighning POC
//
//
#define BETWEEN 2579
#define DURATION 43
#define TIMES 7
#define LEDPIN 0
unsigned long lastTime = 0;
int waitTime = 0;
void setup()
{
randomSeed(analogRead(2));
pinMode(LEDPIN, OUTPUT);
}
void loop()
{
if (millis() - waitTime > lastTime) // time for a new flash
{
// adjust timing params
lastTime += waitTime;
waitTime = random(BETWEEN);
for (int i=0; i< random(TIMES); i++)
{
digitalWrite(LEDPIN, HIGH);
delay(20 + random(DURATION));
digitalWrite(LEDPIN, LOW);
delay(10);
}
}
// do other stuff here
}
Monday, September 27, 2021
Electrical Connections — WAGO 221
I wanted to share a new method I’m using for making electrical connections in my yard holiday setup. I’ve been looking for something safe, waterproof and ideally modifiable/reusable for when I change my mind/layout.
I’m sure that others have discovered these previously, but I am loving the WAGO 221 lever nuts. Works for AWG 12-24, rated for mains mower amps/volts. Apparently more common in Europe for household wiring, but also certified by UL for household wiring in the US. I’m only using them for 12V 5A DC circuits, but it’s nice to know they’ve been well tested.
I’m using 18g landscaping “lamp” wire and 35mm film canisters for my junction boxes. Here are a few pictures of my set up.
*I have no financial connection with any of this. Just sharing something that works well for me.
** I’ve also tried a similar product that I found on Ali-express. It is much cheaper. But also much lower quality. Perfectly fine for throwing something together, but the wires fit in less well. I’d also never use it with mains power.