Sign in to follow this  
Phoxtane

Light Sensor Block Occupancy Detector (FPGA Control)

Recommended Posts

I'm taking the knowledge I learned from a class last semester and applying it to my long-term layout.

800x452.jpg

The devices pictured here form the basis of a block-occupancy detector system that will be placed within my long-term layout to facilitate some autonomous functions, such as signals, automatic level crossings, and remote switching.

To start with, let's have a quick look at the FPGA development board I'm using for the controller.

15650254130_817fecf9b8_z.jpg

This is the Basys 3 Artix-7 FPGA Trainer board, sold by Digilent. The Artix-7 FPGA chip used here has 33,280 logic cells divided into 5200 slices (each slice containing four 6-input LUTs and eight flip-flops). It runs off of a 5V power supply, delivered either through USB or an external power jack. There are four 2x6 'PMOD' connectors (standard spacing, thankfully), one of which also acts as an analog input. There is also a VGA connector and a full-size USB as well. In addition, there are 16 switches and five pushbuttons available, as well as 16 LEDs that can be accessed by the user. It uses the Xilinx Vivado Design Suite for programming.

Next, we have the sensor I'm currently using.

640x640.jpg

...Or at the very least, something very similar to it. It's one of those fairly generic designs that's copied by everybody and sold for very little, so it doesn't really matter which one you get so long as it looks the same. This, however, is not the final sensor I'll be using - this design is extremely directional, in that it's only sensitive enough for my application when the light source is in front of the module. It turns out that the version which has a photoresistor as its light-sensitive element is much better at detecting the ambient light level, and is actually somewhat cheaper.

These type of sensors will run happily on anything from 3.3-5V, and have two outputs: an analog output, which will vary its voltage from 0V up to the voltage of the supply, and a digital output, which operates in the reverse of what you'd typically expect - that is, it outputs a high signal (high being the voltage of the supply) when the light level is below the trigger point set by the potentiometer, and outputs a low signal whenever the light level is above the trigger point. There is one power LED and an LED that reflects the opposite state of the digital output.

In my first picture, I have attached the VCC pin of the sensor to one of the VCC connections on the Basys 3 - pins 6 and 12 on the PMOD connectors act as 3.3V supplies, with pins 5 and 11 acting as a ground, and pins 1-4 and 7-10 acting as signal lines - and the GND pin on the sensor to one of the ground connections on the Basys 3. The digital output (DO) on the sensor is connected to one of the signal lines on that same PMOD connector, and the analog output (AO) is left unattached (if I connect AO to a ground connection, the sensor acts as if a bright light is in front of it no matter what).

Next, we have to write the code that defines the behavior of the controller!

FPGAs are interesting because rather than a microcontroller executing commands, the code written actually tells the FPGA to re-wire itself internally to produce hardware-only logic that provides the desired behavior (this is where the name Field-Programmable Gate Array comes from). As such, the code isn't written in C or Java, but in Verilog and other Hardware-Descriptive Languages (HDLs). The code files can be treated as individual 'blocks' of logic, and can easily be combined together to produce much more complex behaviors than we see here.

This is the only Verilog module that runs the system currently:

module bodsensortest(led,bodsensor);
output led; // Goes to some LED on the Basys 3

input bodsensor; // Comes from AO on the sensor board

assign led=!bodsensor; // Oddly enough the AO output is an inverse output - it goes LOW when the light level is above the trigger point

endmodule

Here I'm defining a module called 'bodsensortest', with the output 'led' and the input 'bodsensor'. Then I tell the Basys 3 to set the output 'led' to the opposite state of 'bodsensor'.

In addition to building the actual logic, it's advised to write a testbench module that hooks up to your first module and allows you to simulate it before sending the code off to the board:

`timescale 1ns/100ps
module tb_bodsensortest;
reg tbodsensor;

wire tled;

 bodsensortest  dut(tled,tbodsensor);

 initial begin

  $dumpfile("tb_bodsensortest.vcd");
  $dumpvars(0,tb_bodsensortest);

  tbodsensor=0; #40 // Default should be sensor 'uncovered'
  tbodsensor=1; #40 // Sensor now 'covered'

  #20 $finish;   // total sim time: 100ns

 end

endmodule

Here I define the units of time that I'm simulating in, the module, and inputs (reg) and outputs (wire) for the testbench file. Then I tell the system to create a .vcd (timing diagram) file, and in that file examine ALL variables within the testbench file. Then I toggle the state of tbodsensor off and on to simulate something passing over the sensor, with some delays. Finally, I add in a 20ns delay to round it to a nice number.

Lastly, in order to actually make this work on the board, I have to play with a constraints file that tells the board what I/O pins to look at and what variables they correspond to:

## This file is a general .xdc for the Basys3 rev B board
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project
## LEDs
set_property PACKAGE_PIN U16 [get_ports {led}]	
set_property IOSTANDARD LVCMOS33 [get_ports {led}]

##Pmod Header JA
##Sch name = JA10
set_property PACKAGE_PIN G3 [get_ports {bodsensor}]	
set_property IOSTANDARD LVCMOS33 [get_ports {bodsensor}]

Here I'm telling the Basys 3 that one of the LEDs on the board is the output from the first module, and the input for that module comes from one of the PMOD connections.

After this, I plug these files into the Vivado software, and generate a file that's sent to the board. Because FPGAs are volatile, I also told the software to generate a configuration file that's saved in flash memory on the Basys 3 so it can automatically re-configure itself every time I turn it back on, rather than having to reprogram it with a USB. Otherwise, I would only be able to run this program until the Basys 3 was turned off!

All of this makes a little LED on the board turn on and off :classic:

800x452.jpg

800x452.jpg

Also, I've actually got the function backwards - I want the module to follow the backwards behavior of the sensor, as I want there to be a signal whenever a train is passing over the sensor (it makes more logical sense to me that way). However, so far I'm quite pleased with what I've accomplished as we didn't really do much with outside inputs during the class - we stuck mainly to the switches and buttons provided!

Edited by Phoxtane

Share this post


Link to post
Share on other sites

Pretty neat. I've done similar stuff with Arduino, seems like C# is much easier than VDL. I'll bet that little FPGA board cost more than a nice arduino mini, too.

Share this post


Link to post
Share on other sites

Yes very impressive project. It would be cool seeing this eventually dispatch an entire train layout. I know a lot of big HO railroads have signals like this, but this is the first time I've seen it done for Lego.

Edited by xboxtravis7992

Share this post


Link to post
Share on other sites

Interesting. FPGAs aren't the easiest to work with. I guess you can get parallel hardware processing and speed in exchange for complexity. The dev board seems to make it easier without having to wire your own flash memory, JTAG, 3.3V voltage regulator, etc. :classic:

Share this post


Link to post
Share on other sites

800x452.jpg

The new sensors arrived about a week ago, but I've only just now gotten around to getting a comparison of them.

Interestingly enough, the new sensor has all of its labels in English, whereas the old sensor had the labels for its LEDs in Chinese. In addition, the silkscreen labels for the new sensor are no longer underneath the right-angle headers, making it much easier to figure out which pin is which once the cable is attached. The position of the pins is reversed compared to the old one as well, but that shouldn't be a problem - just swap the leads around and it should be a drop-in replacement for the old style sensor. The LDR on the new module should be much better at detecting the ambient light level, whereas the old module is very directional.

Thinking about it now, the old module could be used as a sort of light gate - maybe I'll set up something on a straight section of track that can measure the train's speed through that section? That'd be fun! The next step here is to integrate it into the landscaping on my layout, and test it in its actual working environment.

I'm also assuming that the behavior of this sensor is more or less exactly the same as the older one, given that they appear to use the same comparator IC, but I really should test it to find out first.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.