Hey guys, I'm planning on using de2 board as the brains of a quadcopter for my final project in digital systems design. The only experience I have with FPGAs and verilog are from this semester but I do think this should be a possible task for me. The toughest project we had so far was to make a 4 bit adder/subtractor and display the result in 7 segment displays. However, before starting, I just want to know if its possible to connect a gyro to the de2's expansion headers and also be able to get output to 4 ESCs (speed controllers that regulate the speed at which the motors spin).I know this is possible because I have seen couple videos on youtube of fpga being used instead of a traditional microcontroller. I do have quite a bit of experience in the world of rc planes/quadcopters and I already have a quadcopter that flies already. The size and weight of the de2 board isn't an issue but I would need to know which breakout gyro board to purchase. Short version of what I need to program in verilog: 1. Depending on the gyro inputs, send different PWM signals to all ESCs. 2. Depending on the inputs from the receiver, override the output (to a certain extent) in the above statement. 3. Develop an algorithm for all this. My questions: 1. The ESCs need PWM signal output. How to make this happen? 2. Do the expansion headers accept digital or analog signals? 3. The receiver (which I control by from a radio), can send PWM our PPM out. Which signal would the headers rather accept? PWM would mean 4 different wires, PPM would mean all the data going in 1 wire. ppm and pwm are explained here. (http://www.endurance-rc.com/ppmtut.php) 4. What gyro (and maybe accelerometer) board should I get? Looking to spend less than $10. 5. Is all this possible to do without too much experience? If you got this far and can help me, that would be great.
Hi Koo,I don't know all the ins and out of the DE2 but I'll try to answer your questions: 1) PWM can be done in a number of ways. Google delta-sigma. PWM is nothing more than a programmable counter that toggles a bit at a certain threshold. 2) Digital for most boards unless there's an A/D converter connected inbetween. Check the DE2 manual 3) Whichever you feel is best for your application. 4) I have no clue. Have you checked Sparkfun yet? 5) Probably not. Personally, I think a microcontroller would probably be a better solution. Most micros have D/A converters, PWM, and pretty much everything else under the sun for less than a few bucks. Unless your design is completely static (i.e. it's a simple, fixed function) I'd go with an Atmel / Microchip solution. Gets you a free IDE as well! -Mux
--- Quote Start --- Hi Koo, I don't know all the ins and out of the DE2 but I'll try to answer your questions: 1) PWM can be done in a number of ways. Google delta-sigma. PWM is nothing more than a programmable counter that toggles a bit at a certain threshold. 2) Digital for most boards unless there's an A/D converter connected inbetween. Check the DE2 manual 3) Whichever you feel is best for your application. 4) I have no clue. Have you checked Sparkfun yet? 5) Probably not. Personally, I think a microcontroller would probably be a better solution. Most micros have D/A converters, PWM, and pretty much everything else under the sun for less than a few bucks. Unless your design is completely static (i.e. it's a simple, fixed function) I'd go with an Atmel / Microchip solution. Gets you a free IDE as well! -Mux --- Quote End --- Thanks for the input. I'm a bit stuck on the de2 board since the whole course is about transistors and gates, not that much about programming. We also have bunch of them to do our labs and projects on, so doesn't make sense for me to spend my own money on a more compact FPGA since arduino is out of question. I already have a working quadcopter with a arduino based flight controller with gps hold etc, so I'd rather spend my time making this instead of a video game on the FPGA. I was thinking about using the following gyro/accelerometer combo but won't use the accelerometer. Gyro is enough to keep the quad stable but won't stabilize it. How would I get the input from the gyro to de2? I will talk about this with my instructor in next couple days so hopefully he will give me good info as well. http://www.ebay.com/itm/mpu-6050-module-3-axis-gyroscope-accelerometer-sensor-for-arduino-/281131375...
The problem I have with buying things from eBay is that they often don't come with the datasheet. It looks like the module on eBay uses I2C based but without the datasheet it's a (very light) paperweight. Either way, in order to communicate with anything you'll need to write / find an I2C interface and some sort of state machine / simple CPU to interact with that data..-Mux
--- Quote Start --- I already have a working quadcopter with a arduino based flight controller with gps hold etc --- Quote End --- My suggestion would be to already use what you have, and just work toward substituting the FPGA controller for the arduino controller. i.e. revise your goal to become the development of a drop-in replacement for what you already have in your working system. Not sure if the new inexpensive Altera board with Arduino header might make things easier for that or not. http://www.altera.com/products/devkits/altera/kit-terasic-cyclone-v-gx-starter.html
Quick update:I managed to make a pwm generator and I can now control speed of a brushless motor by flipping switches from the de2 board which sens pwm signals to the ESC. Now I need to make a pwm decoder since my 2.4ghz receiver outputs pwm signals. The period is 20ms but I will need to program code which detects each duty cycle. Also, I found a gyro that I already own that outputs pwm signals instead of i2c. This will make my hard easier since after I get my pwm decoder to work, I can start writing the algorithm that controls each ESC (which then powers the motors). Here is my code for the decoder which I haven't been able to test yet. The pwmsignal has a period of 20ms (50hz) and it will be 1'b1 1-2ms depending if the input is at 100% or at 0%. When input is at 100%, the signal will be 1'b1 for 2ms, when at 50, for 1.5ms and when at 0%, for 1ms. I guess my greatest difficulty is trying to "sync" each 20ms cycle. Ratio should be a value between 0 and 100 and thats what I'm trying to calculate from the pwmsignal. Essentially, when pwmsignal is 1 for 2ms, I want ratio to be at 100 and when pwmsignal is 1 for 1ms, I want it to be at 0. I'd love to hear if anyone has a better way to find the ratio and if my current code would work. --- Quote Start --- module gyro(clk, control, pwm,pwmsignal); input clk; input pwmsignal; input [8:0] control; output pwm; reg pwm; reg [31:0] counter = 32'd0; reg [31:0] signalon = 32'd0; //# of times a sec pwm signal is at 1 reg [31:0] signaloff = 32'd0; //# of time a sec pwm signal is at 0 reg [31:0] ratio = 32'd0; always @ (posedge clk) begin counter <= counter+1; if (pwmsignal == 1'b1) begin signalon <= signalon+1; end else begin signaloff <= signaloff+1; end if ((counter >= 32'd950000)&&(signalon >=500)) //clock speed is 50,000,000hz, signalon >= 500 in case there is error begin //we want to refresh signal 50 time a sec counter <= 32'b0; ratio <= ((signalon-10'd50000)/5000); //max signalon is 100,000 min is 50,000. This way answer is between 0 and 100 end else begin end end endmodule --- Quote End ---
--- Quote Start --- I guess my greatest difficulty is trying to "sync" each 20ms cycle. --- Quote End --- You probably need to add edge detection. With your faster (50MHz?) clock, do something like below, or maybe adding a synchronizer chain.
reg pwm_prev; // previous sample wire pwm_rising_edge; wire pwm_falling_edge; always @(posedge clk) begin pwm_prev <= pwm; // store the current pwm value and save it for later (until next clock) end assign pwm_rising_edge = pwm & ~pwm_prev; assign pwm_falling_edge = ~pwm & pwm_prev;Then alter your existing counter management to do something like compute your percent value and reset the counters when ' pwm_falling_edge == 1'b1 ' Small comment about your code:
ratio <= ((signalon-10'd50000)/5000);At some point you are going to want to think of some clever way to avoid doing math like this that uses up FPGA resources, but for now you probably have other things to figure out.
Hehe, the forum admins took more than 10 days to approve my post since I'm a new user here. I actually managed to get the whole thing working. I first had a very similar algorithm to the code I posted initially and had the counter reset itself when ((signalon>50000)&&(counter>400000)) and also count the ratio at that point. It worked fairly well but the number varied a bit couple times a second and this wasn't accetable for me. I measured the period of the signal with an oscilloscope and it was 18ms. I tried changing counter?899900 but this didn't work either.Then I just had a great idea in shower which made a ton of sense and the code simpler as well. It works flawlessly with virtually no deviation from number 0 to 100 when the controller stick isn't moving. Now I'm facing yet another problem. I have 2 choices for the gyros. I can either use one that I've used in my RC airplanes that give me 50hz update rate with pwm signals or I can use a mpu 6050 (http://www.ebay.com/itm/new-mpu-6050-module-3-axis-gyroscope-accelerometer-module-for-arduino-mpu-60...) that I also have now. The mpu 6050 would give me really good refresh rates but requires i2c thingy which I really don't know how to do. I'm done quite a bit of research on how to implement the i2c signal but couldn't find any simple explanation. The minimum refresh rates that the ESCs have to have to keep the quad in the air is about 200hz. 300hz gives stable flight and 400-490hz is butter smooth. So I imagine that 50hz refresh rate from the gyro thats outputting pwm signals won't get the quad up in the air. However, as long as I'm able to control the motors of the quad from RC controller and have gyros do some work, my prof will give me close to full credit on the project. Here is the whole code for the PWM decoder that works great.
module gyro(clk, control, pwm,pwmsignal,ratio); input clk; input pwmsignal; input control; output pwm; output ratio; reg pwm; reg counter; reg signalon; //# of times a sec pwm signal is at 1 reg signaloff; //# of time a sec pwm signal is at 0 reg ratio; reg tempcounter; reg tempratio; always @ (posedge clk) begin if (counter<32'd50) //whenever the counter is reset, signalon is also reset begin signalon <= 32'd0; signaloff <= 32'd0; end else begin end tempcounter <= tempcounter+1; counter <= counter+1; if (pwmsignal == 1'b1) begin signalon <= signalon+1; end else begin if (signalon>50000-(control*40)) begin tempratio <= ((signalon - (32'd50000-(control*20)))/(32'd500)); signalon <= 1'b0; counter <= 1'b0; end else begin end end if (tempcounter >= (32'd50000)) begin tempcounter <= 32'd0; ratio <= tempratio; end else begin end end endmodule
--- Quote Start --- requires i2c thingy which I really don't know how to do. --- Quote End --- What part of the I2C thingy did you get confused on? A good starting point is here: http://www.alterawiki.com/wiki/i2c_(opencores) Or if you're OK with software, the bit-banged master in pseudo-C on the I2C wikipedia page is good starting point as well. But if you are determined to write your own HDL version, the specification starts here: http://www.nxp.com/documents/user_manual/um10204.pdf