Crafting with Components and Code

I purchased an Arduino for beginners kit along with a multi-relay and a PIR sensor. Richard from Proto-pic was very helpful and also provided me with the ” … ” kit.

Richard’s electronic components shop sells mostly online at https://proto-pic.co.uk/, but they also have a location in Kirkcaldy, Scotland. Due to Covid, they weren’t open to the general public – but Richard kindly opened up and met me there in person. He was extremely helpful with my project and discussed Arduino technology with a beginner such as myself. He seemed very keen to get more people into this type of making and commented that he had introduced his wife through these kits and she’s really gotten into it. We discussed the variety of options and the complexity that this project could take on, or how to simply make a proof of concept. It was much easier to look at the electronic components and discuss how they would work together in person, this would also prove the same when I went on to work with Neil (read more about that here).

After further investigation, I also purchased 2x Grove PIR Sensors *Adjustable (which I would later learn was not just sensitivity but also time.) as they were a smaller size and had the same Grove plug and go connections.

Creating First Lamp Prototype and Playing with Components

Ultimately this project is about blending traditional craft with modern technology, so I spoke with craftsman Neil Fyffe about our design direction before starting on this portion. You can read more about that here: https://www.francescadare.com/neil-fyffe-workshop-day/

I started with how the electronic components would fit together so that we had a rough idea of how much space we would need. We also decided this lamp would be mains powered, rather than a battery. This meant there was some investigation into how to power each of the 2 light sources along with the board. I purchased this splitter from Amazon, along with a converter kit to change the power to 12V to match the LEDs. Unfortunately at this stage, I didn’t purchase the converter to change from 12V to 5V for the board (which would mean I would later blow out the board by plugging it straight into the 12V power supply (whoops!), besides that it was a brilliant plan, especially for size and aesthetics.

The plan was to have relay switches turn the lights on and off, which would be controlled by the Seeduino board, which would ultimately be taking its instruction from the sensors. Instead of using the 4x relay box – I went with 2x of the individual Grove Relays and plugged them into the board, I also plugged the 2x sensors into the board. The LEDs were then wired with one wire through the relay and another into the converter and ultimately into the power. I tested the converter circuit before adding the relays to make sure my LED strips were set up correctly.

Figuring out the electronic components’ size, wiring and function within the lamp

Once I figured out the components and sizing I moved on to getting some code written for the board so that it knew what we wanted it to do.

Writing and Testing Arduino Code

As with most projects of this nature, the first step was getting my board connected to my computer and able to receive code. This was more of a task than I expected, but being a beginner it will not be as time-consuming on future projects after figuring out setting up on this one.

To test this I wrote the following code with the help of Andrew O’Dowd at Napier which simply switched between the relays in time (in a loop).

/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink
*/
int Relay1 = 2;
int Relay2 = 6;
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {
  Serial.println(analogRead(2));
  digitalWrite(Relay1, HIGH);   // turn the LED on (HIGH is the voltage level)
  digitalWrite(Relay2, LOW); 
  delay(1000);                       // wait for a second
  digitalWrite(Relay1, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(Relay2, HIGH);
  delay(1000);                       // wait for a second


}

I then proceeded to work on setting up the sensors to be inputs and receive the instruction so they could then control the relays (and in turn the LED strips). I looked at the Wiki pages for help on this section and tested a modification of the code that was given at: https://wiki.seeedstudio.com/Grove-Adjustable_PIR_Motion_Sensor/. This was successful in terms of turning on the light, but it would then automatically turn off after a certain amount of time. Leaving me somewhat puzzled.

/*macro definitions of PIR motion sensor pin and LED pin*/
#define PIR_MOTION_SENSOR 2//Use pin 2 to receive the signal from the module 
#define LED 4//the Grove - LED is connected to D4 of Arduino
 
void setup()
{
    pinsInit();
}
 
void loop() 
{
    if(isPeopleDetected())//if it detects the moving people?
        turnOnLED();
    else
        turnOffLED();
}
void pinsInit()
{
    pinMode(PIR_MOTION_SENSOR, INPUT);
    pinMode(LED,OUTPUT);
}
void turnOnLED()
{
    digitalWrite(LED,HIGH);
}
void turnOffLED()
{
    digitalWrite(LED,LOW);
}
/***************************************************************/
/*Function: Detect whether anyone moves in it's detecting range*/
/*Return:-boolean, ture is someone detected.*/
boolean isPeopleDetected()
{
    int sensorValue = digitalRead(PIR_MOTION_SENSOR);
    if(sensorValue == HIGH)//if the sensor value is HIGH?
    {
        return true;//yes,return ture
    }
    else
    {
        return false;//no,return false
    }
}

We were looking to have the sensors act as touchless light switches, where one motion would turn the light on, and then the second motion would turn the light back off. As I didn’t realise at first that the timer was built into the sensor it took some time to figure out why this was happening without any timer code loaded. I reached out to Richard for advice, and I also posted on Reddit for some help.

After taking a step back I thought maybe it wasn’t the code, and I looked again at the specifications of the sensors (aha!), which revealed the problem. I spoke with RS PRO (where I purchased the adjustable sensors), who confirmed I would need either the Mini Grove Sensor, or the simpler Grove Digital PIR Sensor or Grove PIR Sensor. I wasn’t able to get any of these before my workshop day with Neil – so I set out to make the best of the components I had (as many Designer Makers do).

Arduino works on a simple IF – THEN style logic, and I knew that I could adjust the sensor to have a short timer (under 3 seconds), so ultimately what I wanted was to tell the relay to stay on once it received the first signal and to not turn off until it received another one. This meant changing the sensors to Analog inputs and figuring out a way to tell the board to wait 3 seconds before looking for another sensor input. Because Arduino also works on a simple Loop function and using delay() would start to create unwanted delays, I knew that was probably not the way to go. I could see on the input that the sensor would send readings while the timer was running and then go back to 0. The problem with extending the delay and saying turn on when you see a change in reading meant the light would just switch on and off. What I really needed was to say “IF you see a reading THEN turn on the relay, and wait while the timer runs out, but keep the light on.” THEN to have the light turn off I was essentially asking the board to “check only after 3 seconds that there is a change in the sensor input”. This way it would know it was from a new instruction and not from the in-built timer.

Essentially I need the write a code that would trick the onboard timer. And after hunting around various chat boards and Wiki pages, it looked like using millis() to start an onboard timer was the way to go. This worked a treat (you can see the test video below). Unfortunately copying this over to use on the second sensor just simply didn’t work. It is likely because they interfere with each other – ultimately this sensor was then changed to have the longest available on board on time and would work as a traditional motion sensor instead of a light. (this change in function would inform our lamp base design decisions later by moving the sensor to the side – so it worked as a ‘presence’ sensor – read more here). I do realise this is a more complicated way of doing this, and buying new sensors may have been easier, but it’s all part of the crafting/making process, so I did feel a great sense of accomplishment in working it out this way. (Neil also has a similar moment when he realises he could have made a portion of the woodwork crafting easier – but again, it adds a unique flair and stamp).

Video of motion sensor test to the light switch, after replacing code with millis() as a workaround

const int ledPin =  LED_BUILTIN;               // the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
int relay1State = LOW;
int relay2State = LOW;

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated
unsigned long previousSensorRead1 = 0; 
unsigned long previousSensorRead2 = 0; 
unsigned long time;

// constants won't change:
const long sensorInt1 = 3000;


// board assignments:
const int relay1 = 2;
const int relay2 = 3;
const int Sensor1 = A0;
const int Sensor2 = A2;

// the setup function runs once when you press reset or power the board

void setup() {
// set the digital pin as output:
  pinMode(ledPin, OUTPUT); 
// set others:
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  Serial.begin(9600);
}

// the loop function runs over and over again forever

void loop() {  
  
delay (1050);
   
 // here is where you'd put code that needs to be running all the time.

int sensorValue1 = analogRead(Sensor1); 
int sensorValue2 = analogRead(Sensor2); 
unsigned long currentMillis = millis();


//TIME
  Serial.print("MillisSinceStart: ");
  //prints time since program started
  Serial.println(currentMillis);
  // wait so as not to send massive amounts of data
  delay(1);

 //SENSOR READING PRINTING
    Serial.print("1.");
    Serial.println(sensorValue1);
    delay(1);
    Serial.print("2.");
    Serial.println(sensorValue2);
    delay(1);

 
 // RELAY1
  if (sensorValue1 > 1.5) {
    
     if (currentMillis - previousSensorRead1 >= sensorInt1) {
    previousSensorRead1 = currentMillis;
     
     if (relay1State == LOW) {
      relay1State = HIGH;
    } 
       
    else {
      relay1State = LOW;
    }
    digitalWrite(relay1, relay1State);
  }}

// RELAY2
  if (sensorValue2 > 2.5) {
        
    if (relay2State == LOW) {
  }
      relay2State = HIGH;
    } 
        
    else {
      relay2State = LOW;
    }
    digitalWrite(relay2, relay2State);

//Loop End
  }

After getting a new board and equipped with our final design direction, I added a 12V to 5V converter to protect the board, then completed and loaded the following code – and finally shared our project with the online community.

Working on this project I realized how many different ways there are to achieve the same, or at least similar results, from different components to writing the code. It also takes some trial and error, as well as experience to get the electronics to work. This type of making is in my option the craft of the modern age and we may look back in hundreds of years and consider Arduino coding a ‘traditional craft’ just like we think of woodworking.


This post relates to a project page, view the project page to see other related posts and outcomes.

Click Here to return to Journal Posts on Project Page
or click Next Post below to keep reading posts in this category