Sunday, 8 September 2019

Counters in Verilog with the ULX3S

It's time for another learning experience with the ULX3S.  When using FPGAS or Microcontrollers in general it's very useful to generate and use counters.  Counters as their name suggest are ways time can be added to logic circuits.  If you wanted an LED to flash once a second use a counter.  If you want several LEDS to flash at different rates independently use several counters...If you want to ensure an event occurs at a specific point in time...use a counter.

Counters in FPGA are particularly cool as you can have as many of them as you like or need, unlike microcontrollers.  The other thing is that the counters are all independent of each other in an FPGA.  So multiple counters can be used to control things without affecting the operating of anything else...that's very hard to achieve with a microcontroller...the program flow is always linear.

Lets make a counter flash an LED once a second. In order to do that we need to know a couple of things:

What is the clock speed of the oscillator used on the ULX3S development board?
What is the control logic for the LEDS (active high or active low)?

We can find these answers either from the schematic of the ULX3S or from the constraints file.  Both of which are helpfully available here:

https://github.com/emard/ulx3s

https://github.com/emard/ulx3s-examples/blob/master/README.md

The schematic is broken down into several pages and was created in KiCad.  There is also a PDF version here:

https://github.com/emard/ulx3s/blob/master/doc/schematics.pdf

We are interested in page 4 called 'Blinkey' and page 6 called 'USB'.  Blinkey shows the eight LEDS referenced from zero to seven in the centre of the page four in cell B,3.  The LEDS are common ground connected which means they are 'active high' - A control signal from 'Bank 7' the FPGA needs to be high in order to get an LED to turn on.  The current limiting resistors used are 549 ohms so with 3.3 Vdc logic the current flowing through each LED when on will be 6 mA - bright enough! I've used FPGA development boards in the past where the IO was active low so its useful information to know.


The oscillator is in cell A, 3 on the top middle of the page and it is referenced as being 25 MHz - also useful to know.  It is of course possible to use phase lock loops to generate faster clock signals if that is what is required.


The User Constraints File or UCF as it is sometimes referred to is a list of information which tells the software which pins on the FPGA are connected to what and more usefully how they are referred to.  We could write our own UCF file if we wanted to and for complicated designs or if we had created our own circuit with an FPGA we would have to write our own. Helpfully the board designer of the ulx3s (EMARD) has written one for us. When we come to write the verilog code we can use the same naming convention and that way we don't have to write our own UCF file.

The sections we are interested in are:

# The clock "usb" and "gpdi" sheet
LOCATE COMP "clk_25mhz" SITE "G2";
IOBUF  PORT "clk_25mhz" PULLMODE=NONE IO_TYPE=LVCMOS33;
FREQUENCY PORT "clk_25mhz" 25 MHZ;

and

## LED indicators "blinkey" and "gpio" sheet
LOCATE COMP "led[7]" SITE "H3";
LOCATE COMP "led[6]" SITE "E1";
LOCATE COMP "led[5]" SITE "E2";
LOCATE COMP "led[4]" SITE "D1";
LOCATE COMP "led[3]" SITE "D2";
LOCATE COMP "led[2]" SITE "C1";
LOCATE COMP "led[1]" SITE "C2";
LOCATE COMP "led[0]" SITE "B2";
IOBUF  PORT "led[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF  PORT "led[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF  PORT "led[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF  PORT "led[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF  PORT "led[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF  PORT "led[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF  PORT "led[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
IOBUF  PORT "led[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;

Just for reference a hash ( '#' ) symbol before a line means that the text after that is a comment

LOCATE COMP means to locate the drive logic to a particular section within the FPGA fabric.
IOBUF  PORT means the line is to be configured as a buffered input or output..
PULLMODE=NONE means the line will not have an internal pull up or pull down resistor enabled.
IO_TYPE=LVCMOS33 means the line will be configured to be low voltage CMOS at 3.3 Vdc.
DRIVE=4 means the line will be able to source 16 mA of current.  Drive 1 = 4 mA, Drive 2 = 8 mA, Drive 3 = 12 mA and finally drive 4 - 16 mA

When we write the verilog code we need to refer to the clock as clk_25mhz and the individual leds as led[0]

I was really hoping to use a program called IceStudio to program the ulx3s as it is essentially a graphical front end for apio which collates the usage of Yosys, Ptrellis and NextPNR.  Unfortunately the developers of IceStudio do not wish to add the ulx3s to the list of supported development boards.  They have their reasons for doing that.  I suspect it would be possible to fork IceStudio to work with ULX3S but I'm not going to do that as:
  1. I don't have the skill!
  2. I don't have the time to learn the skill!
  3. I don't want to annoy the IceStudio developers because they are nice guys and have worked hard.
I can use the program to demonstrate what we are going to do though...very useful. I find graphical information easier to pick up over seeing lines of HDL Syntax.



The diagram is meant to show that we have one input called clk_25mhz, we have two outputs called LED and wifi_gpio.

The blue box labelled PrescalerN is some pre-written code which basically is a verilog counter module.  It will take the clock input, count how many clock pulses there are and when it has reached 25 000 000 counts it will send a signal to the LED output.  The wifi_gpio output will be set high.

In verilog code this looks like this:

module top (
    input clk_25mhz,            // 25 MHz clock input 
    output reg led [7:0] = 1'b0,   // 8 Bit LED Output register, set LED[0] to be in a predefined state
    output wifi_gpio0     // Output for Wifi enable 
);
    reg [24:0] count = 0;          // Register for the counter
 
    always @(posedge clk_25mhz)    // Interrupt at the positive 25 MHz clock edge
    begin
       if (count == 25000000)    // If the count register has reached 25 million
                begin
                    led0 <= ~led0; // toggle the LED[0] On and OFF with a one second interval.
                    count <= 1'b0; // and reset the count to 1 (binary) 
                end
            else                   // else
                begin    
                    count <= count + 1'd1; // increment the count by 1
                end
    end

    assign wifi_gpio0 = 1'b1; //set the wifi_gpio High

endmodule

The code should be fairly easy to follow. The wifi_gpio input is only needed if your board has an ESP32. The command enables the ESP32 so code can be pushed over wifi. I haven't been doing that at the moment although I should! I'm fairly certain the code will work, I would like to have tested it and in later posts I will be looking into open source verification software like verilator and GTKwave. These programs allow one to simulate verilog code and show how the inputs and outputs will respond.

Lets save the text file (call it top.v) somewhere sensible I chose: C:\msys64\src\Alex\ulx3s\One Second Counter

 Next copy in the constraints file and apio.ini and fire up ConEmu.exe (Windows) and navigate to the folder we just made. It's also at this point that I should state that the board I'm working with has an ECP5 Lattice Semiconductor FPGA so the commands are tailored to it. If you are working with a ECP 12F board or an ECP 85F board you will need to change to commands appropriately.

 

Type the following command to turn the verilog code in top.v into the bit file ready for uploading to
the ulx3s development board: 

apio build --board ulx3s-45f 

The output should look like this:
 
Ignore the warnings... Plug in the ulx3s into your computer using a microUSB cable - exciting times! 

Next lets upload to the ulx3s development board: 

apio upload --board ulx3s-45f 

The output should look like this:
 

Finally its good practice to remove unnecessary files from the build process: 

 apio clean 

 As everything worked you should be able to see an LED flash like in the video below: 


Again not the most exciting thing in the world but it is the hello world of FPGAS and from a tiny acorn an mighty oak tree grows ;) 

That is all for now - Langster!

Thursday, 5 September 2019

ULX3S Open Source FPGA Development Board

I have made no secret of the fact that I am interested in FPGA technology and have been trying to relearn VHDL for some time.  I am also very keen on using open source programs and development tools.

Recently (sometime in the last couple of years) I heard about project IceStorm by Clifford Wolfe.  Mr Wolfe has reverse engineered Lattice Semiconductor's bit-stream files and written a software tool called Yosys which is used to convert verilog files into mapping files which can then be loaded onto a lattice semi-conductor FPGA.  At the moment proprietary FPGA development tools are very large pieces of software which take a lot of space on a hard disk, are feature heavy and not free to use (require licence files), often unsupported (Xilinx WEBise anyone) and I found difficult to use.  I'm not saying they aren't good but if I can use open source software tools I will...I like the idea behind the licensing models.  I'll donate what I can afford and assist wherever I can.

The Yosys Website is here: http://www.clifford.at/yosys/

Project ICE Storm: http://www.clifford.at/icestorm/

Until recently I didn't have a Lattice Semiconductor FPGA development board but that changed when I was offered a ULX3S open source board from the very clever guys at the Radiona Hackspace.  I had come into contact with these gentlemen when I was trying to learn to use the Elbert V2 and Mimas V2 Xilinx based FPGA development boards.  They developed a very cool piece of kit to make use of the open source tools for teaching a Digital Logic course at their local university.

The ULX3S with 3D printed case and buttons!
The board arrived in very good order with a 3D printed case, buttons and some pre-built examples.  I had a quick play with it and intended to write up my experiences and get started on using it.  That was probably this time last year...I am attempting to get back into blogging my experiences, trials and tribulations outside of work as I find it quite useful and I find it forces me to improve on my electronics and development skills.  Anyway...back to the board:

The board is in my opinion, very well designed and implemented.  I particularly like the addition of the ESP32 so files can be uploaded over wifi.

Here are some photos of the board:

The top side of the PCB with buttons, microSD card and display
The underside of the PCB with the ESP32 module
Here is the website for the project: https://radiona.org/ulx3s/

Here is a Hackaday write up: https://hackaday.com/2019/01/14/ulx3s-an-open-source-lattice-ecp5-fpga-pcb/#more-340565

I'll be honest, I bought the board to support the project, I haven't got a project or use in mind.  To be even more honest I still want to re-learn a hardware description language so that when I do have a project in mind I'll be able to make use of the technology.  I do have ideas for a piece of instrumentation but that is a way off and requires a lot more than just the FPGA!

The first thing I did with the board was use it to emulate an Amiga 500 computer using the pre-loaded Minimig project which came ready to play on the board.  All I had to do was grab some amiga disk images and I could play all the games from my misspent youth.  Retro gaming with FPGA devices is a very popular hobby as the hardware is not being emulated but actually realised within the fabric of the device which leads to a more realistic experience.

Playing Lotus Turbo Challenge 2 and Utopia are fun diversions but not quite what I had in mind for the device.

The open source tools all appear to be for linux operating systems only at the moment so I installed Linux Mint on my main PC and got to work installing all of the pieces of software needed from project Ice storm.  

My LinuxFu is not that strong so I may have messed this up somewhere along the way.  I know I have downloaded, and compiled the following pieces of software:

IceStudio
prjtrellis
Yosys
nextPNR

I was then pointed towards the apio project by a colleague and downloaded the windows version of that software along with all the other bits and pieces needed by following the instructions here:

https://github.com/ulx3s/fpga-odysseus

It installed fine although I would ensure that if following the instructions that you don't upgrade the apio software.

Once presented with the command prompt by loading the ConEmu.exe program it is pretty easy to get started:


This screen brought my back to my days of the DOS prompt.  I know the linux command prompt is fairly similar but I just don't use linux enough to be comfortable with it...I am slowly improving though...

I made a folder called Alex and then a sub folder called ulx3s, you could use any folder names you like.  I then copied two files into the folder:

apio.ini - found from the folder C:\msys64\src\fpga-odysseus\tutorials\01-Basics\01-LED
ulx3s_v20.lpf - found from the folder C:\msys64\src\fpga-odysseus\tutorials\01-Basics\01-LED

The apio.ini file is a text file that tells the apio software everything needed to prepare files for upload to the ulx3s board and ulx3s_v20.lpf is the constraints file for the board, it tells apio and all of the other software which pins are connected to what and where between the FPGA and the external peripherals.

I next created a simple text file in notepad++ - you could use any text editor to be honest.  I called it top.v and typed out the following simple program:

//Hello world LED program

//create a module called top
module top (
    output [7:0] led, //create an output vector called 'led' with 8 bits
    output wifi_gpio0 //create an output for the wifi gpio
);
    assign led = 8'b10101010; //set the state of the bits in the vector to the number 170
 // this sets the bits on and off alternately

    assign wifi_gpio0 = 1'b1; // set the wifi gpio wifi high 
endmodule //end the module

Save the file in the directory made previously:

C:\msys64\src\Alex\ulx3s

Next jump to the ConEmu command prompt and make sure all of the files we need are there by typing ls and hit enter :


next type the following: apio build --board ulx3s-45f'

You should see the following displayed, ignore the warning messages:


  The following files will have been created in the directory:

Exciting times....now it is time to upload the program to the FPGA.  Make sure the ULX3S board is plugged into a suitable USB port and powered up.

Type the following command:

apio upload --board ulx3s-45f

If all goes according to plan you should see the following:


Next type the following:

apio clean

This removes all of the unnecessary files created during the processes.  Finally its time to admire your work.  If everything went according to plan you should see the following LED pattern on your ULX3S!


Ok so its nothing special but it's a start. I'm hoping soon to do a bit more with it.  I hear good things about something called ICE Studio:

https://icestudio.io/

It doesn't have support for the ulx3s yet but I'm hopeful it can be added soon!

That's all for now - Langster!

Sunday, 28 July 2019

Finishing off the Interactive Confetti Room Controller

Last week I managed to help finish off the interactive confetti room controller.  It which was finally made up of the following components:

1x Arduino Uno R3 clone
1x prototyping shield
1x magnetic door sensor and complementary magnet
3x 10 kΩ resistors
1x DS1307 i2c real time clock module
1x Elegoo 8 channel relay module
5x Single UK mains plug socket extensions
1x 5 Vdc power supply for the Arduino Uno and Relay PCB

The build was put together as follows:


The mains power all came from a single input poorly shown coming in at the bottom left.  This connection was then used to power the 5 Vdc power supply for the arduino and the relay module.  The live connection to the outputs was controlled by the relay PCB between the normally open and common connections.  The relays inputs were connected to the arduino uno digital pins at 11, 10, 9 and 8 respectively.  The door sensor was connected via between 5 Vdc and digital pin 2 of the arduino, a 10  resistor and GND.  The real time clock module was connected to the i2c pins A4 and A5 of the arduino UNO.  The i2c lines were also 'pulled up to 5 Vdc via 10 kΩ resistors to ensure correct operation.  

Note: The Elegoo relay module screw terminals are quite small and it was difficult to insert 1.5 mm diameter mains cable into them.  I ended up getting some thick single core house wiring conductor and using that and when connecting the live conductor to that.  I then covered the lot in hot glue and insulating tape to try to prevent the exposed live being touched.  As everything is going inside a box it shouldn't be an issue anyway.  The final user who will be using this controller and developing the firmware was clearly warned!  

The whole assembly was mounted to a laser cut wooden baseboard...as this turned out to be a little undersized I then put the whole lot inside a 230 x 230 x 120 mm laser cut wooden box.  Strain relief was added to all cables using some cable ties. The lid was left off while the firmware was developed by the customer.  I assisted where I was requested but I am not the best at coding and was also short on time so I left them to it!

Here is a photo of the kit inside the box:


Here is a photo of the box with it's unattached lid:


Well that's it for this quick project.  I may well add source code and video of the final effect when I get the chance to see it!  I'm aware this post lacks the usual detail but there wasn't much to write about.

That's all for now - Langster!

Sunday, 7 July 2019

Elegoo 8 Channel Relay Module Tutorial

Carrying on from the previous post about an interactive confetti room...

https://langster1980.blogspot.com/2019/07/interactive-confetti-room-project.html

Lets get out the 8 channel relay PCB and see what makes it tick.

Here are the specifications of the device in case it is needed:

● Output Channels: 8
● Operating Voltage: 5 Vdc
● Operating Current: 480 ma
● Switching Voltages: 250 Vac at 10 Amps, 30 Vdc at 10 A

● Mechanical Dimensions (Length*Width*Height): 137 mm x 56 mm x 17 mm (5.4" x 2.2" x 0.7")
● Mounting Hole Size: 3 mm (0.12")
● Mounting Hole Centres (L*W): 132 x 50 mm (5.2" x 2")

Here is the schematic diagram again:


I connected up the relay board to the Arduino R3 as shown in the diagram below:
This connection arrangement will actuate the channel 1 relay switching the positive feed (+5 Vdc) on it's common and normally closed connections.  Anything connected between the common pin and the normally closed pin will be switched, It could be anything as long as it is within the specifications of the relay contacts.  The normally open pin will also be switched as the common pin is in the middle of the switching contacts.

We want to write some simple test code to drive the relay coil on channel one on and off for a brief period of time:

1.  Initialise control variables
2.  Start the Serial Monitor
3.  Set the relay drive pins to be outputs
4.  Open channel 1 relay contacts
5.  Wait half a second
6.  Close channel 1 relay contacts
7.  Loop back to step 4 and repeat continuously

Here is the code:

/* Langster's Test Code for 
 *  Elegoo 8 Channel Relay PCB
 *  07/07/2019
 *  Test circuit output is a Green 5 mm LED 
 *  and a 220 Ohm resistor connected
 *  between common and Normally Closed screw
 *  terminals on the channel 1 relay outputs
 *  
 *  The Elegoo relay module is connected to
 *  an Arduino Uno R3 on the following pins:
 *  
 *  GND connects to GND of the Arduino
 *  IN1 connects to Pin 11 of the Arduino
 *  IN1 connects to Pin 10 of the Arduino
 *  IN2 connects to Pin 9 of the Arduino
 *  IN3 connects to Pin 8 of the Arduino
 *  IN4 connects to Pin 7 of the Arduino
 *  IN5 connects to Pin 6 of the Arduino
 *  IN6 connects to Pin 5 of the Arduino
 *  IN7 connects to Pin 4 of the Arduino
 *  VCC connects to Vin pin of the Arduino
 */

int eightChanRelayIN1 = 11;   //variable for relay channel 1 drive pin
int eightChanRelayIN2 = 10;   //variable for relay channel 2 drive pin
int eightChanRelayIN3 = 9;   //variable for relay channel 3 drive pin
int eightChanRelayIN4 = 8;   //variable for relay channel 4 drive pin
int eightChanRelayIN5 = 7;   //variable for relay channel 5 drive pin
int eightChanRelayIN6 = 6;   //variable for relay channel 6 drive pin
int eightChanRelayIN7 = 5;   //variable for relay channel 7 drive pin
int eightChanRelayIN8 = 4;   //variable for relay channel 8 drive pin

int relayDwellTimeMS = 500; //variable for setting the dwell time a relay is actuated for

void setup() {

Serial.begin(9600);      // open the serial port at 9600 bps:
pinMode(eightChanRelayIN1, OUTPUT); //set the relay drive pin for channel 1 to be an output
pinMode(eightChanRelayIN2, OUTPUT); //set the relay drive pin for channel 2 to be an output
pinMode(eightChanRelayIN3, OUTPUT); //set the relay drive pin for channel 3 to be an output
pinMode(eightChanRelayIN4, OUTPUT); //set the relay drive pin for channel 4 to be an output
pinMode(eightChanRelayIN5, OUTPUT); //set the relay drive pin for channel 5 to be an output
pinMode(eightChanRelayIN6, OUTPUT); //set the relay drive pin for channel 6 to be an output
pinMode(eightChanRelayIN7, OUTPUT); //set the relay drive pin for channel 7 to be an output
pinMode(eightChanRelayIN8, OUTPUT); //set the relay drive pin for channel 8 to be an output

}

void loop() {

digitalWrite(eightChanRelayIN1, LOW);   //switch relay channel 1
delay(relayDwellTimeMS);                //wait for the dwell time (500 ms)
digitalWrite(eightChanRelayIN1, HIGH);  //switch relay channel 1
delay(relayDwellTimeMS);                //wait for the dwell time (500 ms)
 
}

The code is fairly easy to understand.  Each relay channel has been assigned a variable to easily reference it.  A variable to select how long the relay will be open or closed is also added, commonly known as the dwell time.

Next in the setup function the serial terminal is initialised although it isn't actually used for anything (I had plans to add serial messages and then didn't bother).

After that all the relay channel drive pins are set to outputs. 

Finally in the loop function the relay on channel one is driven low which opens it's contacts.  The contacts stay open for half a second and then the contacts are closed - the pin is driven high for half a second and then the function loops back to the start and repeats.

Here is a short video of things in action:


Things to note - The relay drive pins are active low. That means in order to make a relay switch the contact open the drive pin must be driven low.

It would not be difficult to modify the code to drive all of the relays, just modify the code in the loop section:

void loop() {

  digitalWrite(eightChanRelayIN1, LOW);    //switch relay channel 1
  digitalWrite(eightChanRelayIN2, LOW);    //switch relay channel 2
  digitalWrite(eightChanRelayIN3, LOW);    //switch relay channel 3
  digitalWrite(eightChanRelayIN4, LOW);    //switch relay channel 4
  digitalWrite(eightChanRelayIN5, LOW);    //switch relay channel 5
  digitalWrite(eightChanRelayIN6, LOW);    //switch relay channel 6
  digitalWrite(eightChanRelayIN7, LOW);    //switch relay channel 7
  digitalWrite(eightChanRelayIN8, LOW);    //switch relay channel 8
  
  delay(relayDwellTimeMS);                 //wait for the dwell time (500 ms)
  
  digitalWrite(eightChanRelayIN1, HIGH);   //switch relay channel 1
  digitalWrite(eightChanRelayIN2, HIGH);   //switch relay channel 2
  digitalWrite(eightChanRelayIN3, HIGH);   //switch relay channel 3
  digitalWrite(eightChanRelayIN4, HIGH);   //switch relay channel 4
  digitalWrite(eightChanRelayIN5, HIGH);   //switch relay channel 5
  digitalWrite(eightChanRelayIN6, HIGH);   //switch relay channel 6
  digitalWrite(eightChanRelayIN7, HIGH);   //switch relay channel 7
  digitalWrite(eightChanRelayIN8, HIGH);   //switch relay channel 8
  
  delay(relayDwellTimeMS);                //wait for the dwell time (500 ms)
 
}

I haven't got eight LEDS to hand to give a demonstration of this but I have tested the code and the circuit it works perfectly...the clicking of the relays sounds a lot like an old fashioned watch tick or a metronome.

If one were to change value in the dwell time variable the relays will switch more quickly or slowly...the maximum speed they should be switched is 100 ms...any faster will work but might damage the relays and the noise exceptionally irritating! 

The code can also be modified to independently switch each relay with independent dwell times as required. 

That's about it for now, take care - Langster!

Thursday, 4 July 2019

Interactive Confetti Room Project

I was recently asked to help develop the electronics for an event.  The basic idea is that people would enter a room filled with different coloured confetti and air blowers.  These air blowers would be energised for short periods of time in prescribed sequences blowing the confetti about the room in a colourful display.  Hopefully a little bit reminiscent of a final game in a classic British TV program - the Crystal Maze!  If people aren't aware of the cult classic of the crystal maze then a link is below:


The part I'm referring to is this, don't watch all of it! - skip to 2:17 for the important bit:



Hopefully people reading this post will get what I mean.  Anyway...in order to create a similar effect Five air blower units will be sourced and placed inside a 15 mroom.  The fan units will be placed in the corners with one unit in the mid point in effort to ensure there is some form of uniform airflow.  The coloured confetti is placed in front of the fan units and when people enter the room and the door is closed the fans will come on in a prescribed sequence creating an atmospheric effect.  This hasn't been tried and tested yet so some development of the experience may be required...I'll probably leave that part to others as I haven't the time and to be honest I have only been asked to help develop the kit not the experience...I'll help out where I can but getting the desired effect is up to the customer...I'll provide the tools not the results...

The above diagram hopefully gets the general idea across.

The fan blower units have already been selected and are linked below:


Vacmaster Air Mover | High Power, Energy Efficient Turbo Fan/Blower/Dryer
Image Credit - Vacmaster, via Amazon.co.uk
The specifications given via the Amazon product page are:

  • POWERFUL AIR FLOW - The 150 W motor drives 266 litres of ambient air per second for rapid drying and cooling.
  • ENERGY EFFICIENT - Consumes 90% less power than a conventional 1000 W fan heater.
  • 3 TILT POSITIONS - Tilts at 45 degrees, horizontally and vertically for precise, focused air flow.
  • 3 POWER SETTINGS - Low, medium and high speed settings for quiet or fast drying.
  • INTEGRATED EXTENSION SOCKET - For powering additional Air Movers from a single wall socket. Daisy-chain them together to cover a large area.
The vendor doesn't mention the mains supply voltage required but as this is the UK and it's being sourced via amazon UK I'm going to assume the supply is 230 Vac.  The current draw will therefore be 0.65 Amps - as Current (Amps) = Power (Watts) / Volts from Ohms Law:

150 Watts / 230 Vac = 0.6521739130434782608695652173913‬ Amps
or 0.65 Amps to two significant figures...

Lets write some requirements:

  • Switch five fans on and off independently in a pre-arranged sequence
  • Choose specific times of day when fans will come on and off
  • Ensure fans can only actuate when the door to the room is closed.
  • Ensure fans have independent overrides for safety - be able to turn fans on/off via control buttons
  • The switching requirement is 230 Vac at 0.65 Amps for each fan 

There are several ways this could be achieved.  As time is of the essence...as it always seems to be, I'm going to use relays to switch the mains feed to the fans.  The relays will be controlled via a microcontroller which can be communicated with using a serial terminal or via the buttons which will be on the front panel of the control unit.  If necessary I'll add an indication LED and maybe a buzzer to show when the fans are about to begin operation...I suspect the fan noise will make that clear to all concerned though - 😃

I could design my own relay control PCB complete with drive electronics or I could make use of a pre-made module...again time and budget suggests I go with something off the shelf.  I need a five channel relay module capable of switching 230 Vac at 0.65 Amps. I found this module on Amazon.co.uk and it looks to have everything needed...that'll save some time!

Elegoo 8 Channel Relay Module - via Amazon.co.uk

Image Credit - Elegoo 8 channel Relay Module via Amazon.co.uk
There are eight relays are capable of switching 230 Vac at 10 Amps - far more than we need and they meet the switching requirements.  They can be driven from 5 Vdc which means that they can be driven from a five volt tolerant microcontroller output.  The relay drive coils are optically isolated so the microcontroller won't be affected by the relay switching.  There is an LED (light emitting diode) at each relay channel to display when the relay coil is being driven.  The cost was a very reasonable GBP £8.99 or USD $11.31 which I would struggle to compete with if I were to design my own version.

The schematic diagram for the relay module is here in case it is needed:

We will also need the following components:

An arduino uno R3 microcontroller or clone - Via Amazon.co.uk
Some Momentary Buttons  - via Amazon.co.uk
Some jumper wires - via Amazon.co.uk
Some tri-colour LEDS - via Amazon.co.uk
Some LED holders - via Amazon.co.uk
Six mains sockets and wire - via Amazon.co.uk
Some connector block - via Amazon.co.uk
A reed switch and magnet - via Amazon.co.uk
A power supply for the Arduino - via Amazon.co.uk

The current plan (always subject to change) is to connect all the above components as follows:


Please excuse the crudeness of the diagram...I didn't have time to sort everything as much as I would have liked but it gets the general idea across...I've missed off the power supply to the arduino.  It is also connected to the incoming mains and then to the dc input socket on the arduino.  Not all of the relays need to be controlled by the arduino so some of the wires can be omitted as necessary and finally the reed switch should have a 10 k resistor pulling it down to 0 Vdc as with the buttons so that it is properly detected by the microcontroller input.

That's enough for now.  The next post will be on testing and using the Elegoo 8 channel relay module.

Take care, especially with mains wiring - Langster!

Thursday, 20 June 2019

How to Drive a Solenoid from a Microcontroller

I haven't posted anything in a long time...I just haven't been motivated enough to do so.  I suppose it could be because I'm busy but its more likely I've just lacked the energy to do anything.

I recently designed a simple FET driver circuit for energising a solenoid.  It wasn't particularly special in my opinion but I thought it might be useful to share the experience so here goes:

I had to drive a solenoid based circuit for an electronic lock from a microcontroller.  As a solenoid is essentially an inductive load I would need a transistor based circuit to control the supply voltage from a 3.3 Vdc signal generated by an STM32 microcontroller.  In order to actuate the solenoid a short pulse (less than a second) was required from a 12 Vdc or 24 Vdc supply.

A solenoid is an electro-magnetic actuator which creates a concentrated magnetic field.  Here are a couple of links about solenoids and how they work:

https://sciencing.com/a-solenoid-work-4567178.html

https://en.wikipedia.org/wiki/Solenoid

A simple switching circuit is all that is required to energise the solenoid coil and actuate it.  Electronic switching can be performed in many ways - a relay switch in itself is a form of electro-magnetic actuator.  In my case I decided to use a Field Effect Transistor or FET.  I've blogged about field effect transistors in the past:

https://langster1980.blogspot.com/2012/09/using-field-effect-transistors.html

The same principles apply.  Recently I read an excellent blog post by James Lewis - 'The Bald Engineer' on some of the misconceptions about using field effect transistors...I recommend looking at James's website.  He writes some excellent articles and makes some great video content on electronics engineering.

https://www.baldengineer.com/7-mosfet-myths-and-misconceptions-addressed.html#more-7748

As I had to drive the field effect transistor directly from a microcontroller pin at 3.3 Vdc I needed what is known as a logic level FET - That is a device that will allow current to flow between the drain and the source pins when the gate pin is supplied with logic level voltages, logic level voltages are normally classed as 1.8 Vdc, 3.3 Vdc and 5 Vdc.  In the case for the microcontroller I am using - an STM32F439 a logic 1 (high) is 3.3 Vdc.  Therefore I needed a FET which had a VGS on threshold that was at or below 3.3 Vdc.  I chose to use the IRLZ44 as I had some of those components and I also had a spice model for them so I can simulate the circuit.

From some brief measurements of my solenoid I found that it had a series resistance of about 33 ohms and I guessed it's inductance at 3 Henrys....I didn't have my LCR meter to hand to measure it....I might dig that out later to see what the inductance actually is.

Here is the datasheet for the IRLZ44: http://www.irf.com/product-info/datasheets/data/irlz44n.pdf

I'm using the T0220 version for my circuit:

Image result for IRLz44

The critical parameters I was interested in are:

VDSS = 55 Vdc - The maximum voltage allowed on the drain pin with respect to the source pin.

RDS(on) = 0.022 Ω - The resistance of the drain with respect to the source pin when the transistor is on.

ID = 47 Amps - The maximum current allowed to flow from the drain to the source.

VGS On Threshold = 2.0 Vdc - The voltage at which the FET turns OFF - Thanks James, I always wrong about this too!  This means in order to turn the FET on (cause conduction between the drain and source pins we need to surpass this this voltage at the gate pin.  If the voltage at the gate pin drops below this voltage the transistor will stop conducting from the drain pin to the source pin.  The parameter name is a little confusing but hey ho...

So what does this all mean.  It means that I can turn the transistor on using an output pin from a
3.3 Vdc microcontroller and that will allow conduction through the drain pin to the source pin which will allow me to control the voltage supplied to the solenoid.

Here is the circuit:

Simple Solenoid Driver Using a Logic Level FET
Here is the circuit's operation.  A 3.3 Vdc pulse will be supplied from the microcontroller.  This pulse is applied to the gate of the IRLZ44 FET through a 270 Ω resistor (R2).  The resistor R2 is present to prevent a large in-rush current being presented to the gate pin of the FET.  It isn't always necessary if one is only applying long slow voltage pulses to the gate.  I always add a resistor as I like to be certain there will not be any in rush current issues.  The 10 kΩ resistor (R1) is a pull down resistor.  It ensures that the gate pin of the IRLZ44 when not driven from the microcontroller is in a known state - low.  It prevents the FET from spuriously switching on or off.  The drain of the FET is connected to the solenoid (modelled in this case by the 33 Ω resistor and the 3 H inductor.  The schottkey diode (D1) is present to prevent the back-emf generated by the inductive load switching on and off damaging the FET.  D1 is sometimes called a 'free wheel diode' or the 'flyback' diode....More on this later.
 
The voltage source VCC and switch S1 are not really present but a way of simulating what the output from the microcontroller will be. If S1 is closed for a short period the signal presented to the gate pin will be similar to the output pulse from the microcontroller.  This pulse voltage will cause the FET to become active allowing current to flow from the drain to the source which in turn will allow voltage to flow through the solenoid causing it to actuate (create a magnetic field which pulls the pin into the coil).

If we were to simulate the operation of the circuit and observe the input and the output with an oscilloscope connected as shown above this is what would be seen:


The red trace is the the solenoid operation and the blue trace is the input from the microcontroller - modelled in this case by the switch S1 and the 3.3 Vdc voltage supply.

So our circuit simulates will and will work.  The FET operates properly from a 3.3 Vdc supply and can go active within a milli-second.  More than adequate for our purpose!

The only thing left I wanted to discuss was the flyback diode D1...it's needed as when an inductive load has voltage and current applied it converts the electrical energy into magnetic energy creating a concentrated magnetic field.  When an inductive load is has the voltage and current removed the magnetic field collapses and any left over energy is passed back to the drive circuit as a large voltage spike.  This spike is often well over 100 Volts for a short period - more than enough to damage the Field Effect Transistor.  Therefore the flyback diode is applied to prevent this damaging voltage spike passing to the FET.

To illustrate the point here is a circuit with a switch added to the flyback diode.  As the switch is open the diode is not connected.  When the magnetic field collapses this is what is passed back to the FET:


Here is the oscilloscope trace:


If the flyback diode was not present in the circuit the FET would fail fairly quickly...

I'll add some photos of the circuit I built shortly to show it in operation.  It works perfectly for my application.  Take care people - Langster!





Here is a quick video of the circuit on a bread board.  It was driving an electronic lock using 5 Vdc as the gate voltage:





Monday, 12 March 2018

AD9850 Signal Generator

I have a bit of free time at the moment and I was looking at previous projects and what equipment I have available to me.

I have couple of bench power supplies, an oscilloscope, a multimeter and a good stock of components for development.  I still don't have a Signal generator!  In previous posts I wrote about how I developed some addon circuitry for an AD9833 breakout board.  I never actually finished that project and I have since decided that there are better DDS signal generator breakout boards available.  I bought an AD9850 breakout board from a maker-faire vendor at least two years ago and it has sat in my breakout boards pile for a long time!

The breakout board is based on the AD9850 from Analog Devices and it's a DDS synthesis circuit.  The datasheet for the device is here:

http://www.analog.com/media/en/technical-documentation/data-sheets/AD9850.pdf

There are lots of tutorials and information available on the internet for how this device works and can be used to make a simple signal generator.  Some of the links I used for reference are below:

http://telecnatron.com/modules/ad9850/index.html

http://kv4qb.blogspot.co.uk/2017/04/the-sa-becomes-sna-jrv3-for-now.html

The number of projects and posts available for this board and how to use it are a testament to how good the device is and how easy it should be to use and get it up and running.  I may yet build a simple scalar network analyser with one to allow for filter and amplifier testing at some point.

For now I just need access to a signal generator.  I should have finished the one I designed years ago or bought one off the shelf!  The off the shelf devices that I see are all still quite expensive and don't have all of the functions I need.  I could probably find one that did meet all of my requirements if I looked hard enough and was prepared to part with a little more money!  The module itself costs £15.00 from various online vendors although I'm certain I paid less for it than that.


Here is the schematic diagram for the AD9850 breakout board:



As can be seen there is a filtered and unfiltered output.  Obviously we want to use the filtered output and see what comes out of the unit.

By connecting the unit up to an arduino and using example code we should be able to get the unit up and generating signals.  From that we can design an amplifier and match the circuit to 50 ohms and hopefully put together a useful piece of test equipment in short order!

Helpfully there are several libraries already written for driving the module using an arduino so that saves some time and effort:

https://github.com/F4GOJ/AD9850

Here is how the module is connected up for testing with an arduino mega:

AD9850 breakout board connected to an Arduino Mega
For connecting up the AD9850 module:

Pin 1 (Vcc), connect to the arduino +5V pin
Pin 2 (W_CLK), connect to the arduino digital pin 8
Pin 3 (FQ_UD), connect to the arduino digital pin 9
Pin 4 (Data), connect to the arduino digital pin 10
Pin 5 (Reset), connect to the arduino digital pin 11
Pin 6 (GND), connect to the arduino GND pin

Pin 10 (Filtered Sine Out), connect to an oscilloscope for testing

Here is the code I used to test the module:

 // Langster's DDS test Code  
 // Date: 12/03/2018  
 // Makes use of m0xpd's DDS Arduino Library  
 // http://m0xpd.blogspot.com  
 // include the DDS Library:  
 #include <DDS.h>  
 // AD9850 Module is connected to the following  
 // arduino pins  
 const int W_CLK = 8;  
 const int FQ_UD = 9;   
 const int DATA = 10;  
 const int RESET = 11;  
 double freq = 0;  
  // Instantiate the DDS...  
  DDS dds(W_CLK, FQ_UD, DATA, RESET);  
 void setup() {  
  // start up the DDS...    
  dds.init();   
  // (Optional) change value if the clock crystal does not resonate at 125MHz...  
  dds.trim(125000000); // enter actual oscillation frequency   
  // start the oscillator...  
  dds.setFrequency(freq);   
 }  
 void loop() {  
  dds.setFrequency(1000); //set the frequency output to 1 kHz   
 }  

The code will initiate the DDS module and then set an output of 1 kHz.

I connected up the filtered sine output to an oscilloscope and here is the result:

1 kHz sine output from Ad9850 DDS Module
A nice clean 1 Vpk to pk, 1 kHz sine wave!  The square wave output was also present and in good shape.  I'm going to perform more testing to check the useable frequency range but so far so good.

By changing the value in the line:

dds.setFrequency(1000); //set the frequency output to 1 kHz

The frequency output is changed.

That's all for now - Langster!