Advice sought - things to do with Arduino and FPGA

I'm not really sure what I'm asking here so please bear with me ....

I'm a software engineer, with a little electronics experience from log ago, and I've played around with Arduino Uno's - I've built the beginnings of a 3-axis CNC machine (just needs hooking up to my Dremel) and I've hacked an optical mouse (posted elsewhere here), I'm not afraid to look stupid, and I'm happy to waste any amount of time learning and having fun.

Ok, now, some years back I bought an FPGA development board, which I played with for a while - it's a Xilinx Spartan 3E Starter Board - I implemented some basic VHDL but never did more than flash a few LEDs and write my name on the LCD panel. I've just rediscovered the FPGA and found it still works (after two house moves).

Now, I'm thinking that there must be something "interesting" I can do with this FPGA and a couple of spare Uno's I have handy. I see that the FPGA mainly uses 3.3V while the Arduino mainly uses 5V, but there's presumably ways to make them talk easily enough. The problem is, that I sit here surrounded by these bits of hardware, an old Weller soldering iron, a large number of years of software experience, an interest professionally in image processing, machine learning etc. and yet I can't think of a single useful or interesting hobby project to do with it all.

I don't want or need to go out and spend any more money - or maybe just a bit for some sensors or whatever - I just want to capitalise on what I've got by putting things together in some way that's meaningful.

So, if you guys had 1) a couple of Uno's, 2) an FPGA board, 3) any amount of software experience, 4) insatiable curiosity, 5) enthusiasm, 6) failing eyesight (ok, forget that, I have new glasses!) .... what would you do to keep yourself occupied?

Make a kickass LED cube. We're making a 9x9x9 cube right now, struggling to get Python (3.0? 3.4?) working an HP AMD laptop to have a way to create patterns to send to Arduino that it then drive the cube with. With your software background that part would seem easy to create in the FPGA vs needing a PC connected. Maybe make patterns based on fingers poking at sensors or some kind of interactivity like that.

CrossRoads:
Make a kickass LED cube. We're making a 9x9x9 cube right now, struggling to get Python (3.0? 3.4?) working an HP AMD laptop to have a way to create patterns to send to Arduino that it then drive the cube with. With your software background that part would seem easy to create in the FPGA vs needing a PC connected. Maybe make patterns based on fingers poking at sensors or some kind of interactivity like that.

Thanks - you mean something like a visual theremin maybe? What type of sensors do "finger poking"? Do you mean some sort of proximity sensors? It would be good if you could expand just a little bit and block out for me which parts of the system would have what responsibilities - sorry if I'm missing the obvious .... I really appreciate the fast reply :slight_smile:

  • fast encryption/decryption between two UNO's ?
  • Conway's game of life, calculated in the FPGA ?
  • if you have sensors you could use multiple Arduinos to collect samples and do some signal analysis.
  • use the FPGA for a real fast random number generator (is this possible?)
  • ...

I was thinking Arduino could do the LED cube control, the FPGA reads the sensors and makes the patterns. Start simple with just 3D rotating cube, read pots to change spin left/rigth, roll up/down, size change, shape change. Then add touch pad(s). Add capacitive sensors. Add light sensors. Scrolling 3D text.

Thanks Rob,

robtillaart:

  • fast encryption/decryption between two UNO's ?

Encryption/decryption (or even brute-force cracking) was certainly something I stumbled on for FPGAs, also Bitcoin mining and MD5/SHA1 hashing. I'll give this more thought - it's intriguing enough ....

robtillaart:

  • Conway's game of life, calculated in the FPGA ?

I think I've seen this as a demo project for the Xilinx board I've got - part of a VGA tutorial IIRC, not sure where the Arduino comes in, but thanks again for the suggestions...

robtillaart:

  • if you have sensors you could use multiple Arduinos to collect samples and do some signal analysis.

Now, this is where I got stuck - what sensors? Ultrasound? Laser measurement? I did consider trying to use ultrasound as an imaging sensor, but a bit more reading revealed the necessity for an oil/liquid interface to get a good response. Do you know anything about this area? I also thought about using my optical mouse hack with some super-resolution reconstruction to get an improved image, but I can only get ~5fps and need synchronised control of movement - maybe hook up a stepper or two - are there other sensors that can be used (or misused) in this way? Not sure I can use the FPGA as a DSP easily too ... more research needed .....

Many many thanks for the response, much appreciated ....

CrossRoads:
I was thinking Arduino could do the LED cube control, the FPGA reads the sensors and makes the patterns. Start simple with just 3D rotating cube, read pots to change spin left/rigth, roll up/down, size change, shape change. Then add touch pad(s). Add capacitive sensors. Add light sensors. Scrolling 3D text.

Ok, I see what you mean now, thanks - you say you're doing something similar? Is the 9x9x9 LED cube something you've built or is it a unit that can be bought? Any chance of some previews of your project so I can pinch generate some ideas? ]:slight_smile:

EDIT - Ah, Google tells all - http://www.instructables.com/id/Led-Cube-8x8x8/ - now that really is a nice project!

Yes. We’re going 9x9x9 so there are center lines.
I have a board with shift registers all designed to control multiplexing of the display, waiting on delivery so we can assemble it. Wife is assembling the cube, bottom later mounted on a board and soldered to perfboard, 2 more layers ready to be attached once we screw down the perfboard.

Hi Roger, newbie here but I've spent some years in electronic hardware design. I think one promising area you may want to consider is multi-channel PWM LED driving. I designed a 64 channel RGBW LED on an Altera FPGA using Quartus design tools. Being an old school hardware man I wasn't keen on VHDL but went for schematic entry. :astonished: Unfortunately Altera scrapped schematic entry as an option in their later versions of Quartus :open_mouth: so I stuck with 8.2 release, but that's another story.

With a large 14-16 bit resolution PWM array in hardware the arduino would be used for channel selection and control with the various parameters being dispayed on a 20x4 LCD character display. You can drive 16 four colour LEDs or 64 single colour devices or even more depending on what size of FPGA you select. The Altera boards are very cheap now and available from various Chinese manufactures on Fleabay. Just a possibility, but maybe pique your interest.

spreader:
... You can drive 16 four colour LEDs or 64 single colour devices or even more depending on what size of FPGA you select....

Thanks for the ideas - the FPGA I have is a Xilinx Spartan 3E like this one - Boards - which is now replaced by the Spartan 6 range, but the toolset I have still works well on Windows 8.1 (after a bit of tweaking!). It seems to me that this would be up to the job, so I'll keep this in mind ....

Many thanks again :smiley:

Our 9x9x9 cube is coming along. I’ve barely started coding,

Here’s the mapping I am doing in software from an array of 16-bit x 9 rows/layer x 9 layer (81 ints) to array of 12 bytes/layer shift x 9 layers for multiplexing.
This mapping is pretty much done as 81 instructions and takes 844uS.
I multiplex with data sent out every 3000uS, so there’s not a lot of time for data manipulation for rotating the cube or something.
Having an FPGA to do that would help a lot. Or going to a faster processor I guess.

/********* done working the patterns, manipulate into the mux array  **********/
    // add indexing into the working array for the 9 layers, or double index or whatever

    /********** layer 0 ***************/
    // takes 844 to 848uS to do this

    //Serial.println (micros());
    layer = 0;
    // anodeArray[11], int 8, bits 8-1
    anodeArray[(layer*anodeArrayInterval)+11] = ( workingArray[(layer*layerNum)+8] & 0b0000000111111110)>>1; 

    // anodeArray[10], int 8  bit 0, int 7 bits 6 to 2
    anodeArray[(layer*anodeArrayInterval)+10] = ( ((workingArray[(layer*layerNum)+8] & 0b0000000000000001)<<7) | ((workingArray[(layer*layerNum)+7] & 0b0000000111111100)>>2) );

    // anodeArray[9], int 7 bits 1, 0, int 6 bits 8 to 3
    anodeArray[(layer*anodeArrayInterval)+9] = (  ((workingArray[(layer*layerNum)+7] & 0b0000000000000011)<<6) | ((workingArray[(layer*layerNum)+6] & 0b0000000111111000)>> 3) );

    // anodeArray[8], int 6 bits 2-1-0, int 5 bits 8 to 4
    anodeArray[(layer*anodeArrayInterval)+8] = (  ((workingArray[(layer*layerNum)+6] & 0b0000000000000111)<<5) | ((workingArray[(layer*layerNum)+5] & 0b0000000111110000)>> 4) );

    // anodeArray[7], int 5 bits 3 to 0, int 4 bits 8 to 5
    anodeArray[(layer*anodeArrayInterval)+7] = (  ((workingArray[(layer*layerNum)+5] & 0b0000000000001111)<<4) | ((workingArray[(layer*layerNum)+4] & 0b0000000111100000)>> 5) );

    // anodeArray[6], int 4 bits 4 to 0, int 3 bits 8,7,6
    anodeArray[(layer*anodeArrayInterval)+6] = (  ((workingArray[(layer*layerNum)+4] & 0b0000000000011111)<<3) | ((workingArray[(layer*layerNum)+3] & 0b0000000111000000)>> 6) );

    // anodeArray[5], int 3 bits 5 to 0, int 2 bits 8, 7
    anodeArray[(layer*anodeArrayInterval)+5] = (  ((workingArray[(layer*layerNum)+3] & 0b0000000000111111)<<2) | ((workingArray[(layer*layerNum)+2] & 0b0000000110000000)>> 7) );

    // anodeArray[4], int 2 bits 6-0, int 1 bit 8
    anodeArray[(layer*anodeArrayInterval)+4] = (  ((workingArray[(layer*layerNum)+2] & 0b0000000001111111)<<1) | ((workingArray[(layer*layerNum)+1] & 0b0000000100000000)>> 8) );

    // anodeArray[3], int 1 bits 7 to 0
    anodeArray[(layer*anodeArrayInterval)+3] =    workingArray[(layer*layerNum)+1] & 0b0000000011111111 ;

    // anodeArray[2], int 0 bits 8 to 1
    anodeArray[(layer*anodeArrayInterval)+2] = (  workingArray[(layer*layerNum)+0] & 0b0000000111111110) >>1 ;

    // anodeArray[1], int 0 bit 0
    anodeArray[(layer*anodeArrayInterval)+1] =  (workingArray[(layer*layerNum)+0] & 0b0000000000000001) << 7 ;

    // anodeArray[0], not used
    anodeArray[(layer*anodeArrayInterval)+0] = 0;

    /********** layer 1 ***************/

    layer = 1;
    // anodeArray[11], int 8, bits 8-1
    anodeArray[(layer*anodeArrayInterval)+11] = ( workingArray[(layer*layerNum)+8] & 0b0000000111111110)>>1; 

    // anodeArray[10], int 8  bit 0, int 7 bits 6 to 2
    anodeArray[(layer*anodeArrayInterval)+10] = ( ((workingArray[(layer*layerNum)+8] & 0b0000000000000001)<<7) | ((workingArray[(layer*layerNum)+7] & 0b0000000111111100)>>2) );

    // anodeArray[9], int 7 bits 1, 0, int 6 bits 8 to 3
    anodeArray[(layer*anodeArrayInterval)+9] = (  ((workingArray[(layer*layerNum)+7] & 0b0000000000000011)<<6) | ((workingArray[(layer*layerNum)+6] & 0b0000000111111000)>> 3) );

    // anodeArray[8], int 6 bits 2-1-0, int 5 bits 8 to 4
    anodeArray[(layer*anodeArrayInterval)+8] = (  ((workingArray[(layer*layerNum)+6] & 0b0000000000000111)<<5) | ((workingArray[(layer*layerNum)+5] & 0b0000000111110000)>> 4) );

    // anodeArray[7], int 5 bits 3 to 0, int 4 bits 8 to 5
    anodeArray[(layer*anodeArrayInterval)+7] = (  ((workingArray[(layer*layerNum)+5] & 0b0000000000001111)<<4) | ((workingArray[(layer*layerNum)+4] & 0b0000000111100000)>> 5) );

    // anodeArray[6], int 4 bits 4 to 0, int 3 bits 8,7,6
    anodeArray[(layer*anodeArrayInterval)+6] = (  ((workingArray[(layer*layerNum)+4] & 0b0000000000011111)<<3) | ((workingArray[(layer*layerNum)+3] & 0b0000000111000000)>> 6) );

    // anodeArray[5], int 3 bits 5 to 0, int 2 bits 8, 7
    anodeArray[(layer*anodeArrayInterval)+5] = (  ((workingArray[(layer*layerNum)+3] & 0b0000000000111111)<<2) | ((workingArray[(layer*layerNum)+2] & 0b0000000110000000)>> 7) );

    // anodeArray[4], int 2 bits 6-0, int 1 bit 8
    anodeArray[(layer*anodeArrayInterval)+4] = (  ((workingArray[(layer*layerNum)+2] & 0b0000000001111111)<<1) | ((workingArray[(layer*layerNum)+1] & 0b0000000100000000)>> 8) );

    // anodeArray[3], int 1 bits 7 to 0
    anodeArray[(layer*anodeArrayInterval)+3] =    workingArray[(layer*layerNum)+1] & 0b0000000011111111 ;

    // anodeArray[2], int 0 bits 8 to 1
    anodeArray[(layer*layerNum)+2] = (  workingArray[(layer*layerNum)+0] & 0b0000000111111110) >>1 ;

    // anodeArray[1], int 0 bit 0
    anodeArray[(layer*anodeArrayInterval)+1] =  (workingArray[(layer*layerNum)+0] & 0b0000000000000001) << 7 ;

    // anodeArray[0], not used
    anodeArray[(layer*anodeArrayInterval)+0] = 0;

    /********** layer 2 ***************/

    layer = 2;
    /********** end working array to anode array conversion ***************/

Only 2 layers are shown, rest are duplicated. As noted, takes 844uS. I think it’s being done every time now, I need to smarten that up so it only runs when the workingArray has been changed.

An other idea.
How about having a real time FFT with your FPGA, to make a spectrum analiser for audio signals.