0

I'm working on making a servo run off of an FPGA for a digital lock.

My code is as follows:
`timescale 1ns / 1ps


/*
 1 pin for servo--ORANGE CABLE
 red cable-- 5V, brown cable-- GND. 
 Position "0" (1.5 ms pulse) is middle, 
 "90" (~2ms pulse) is all the way to the right,
 "-90" (~1 ms pulse) is all the way to the left.  
 servo stuff:
 http://www.micropik.com/PDF/SG90Servo.pdf
 */


 //All i need to do is set SERVOPWM to 1 and 0 with delays i think
module ServoTestNShit(input M_CLOCK,
                             output [7:0] IO_LED, // IO Board LEDs
                             output reg SERVOPWM);    

    assign IO_LED = 7'b1010101; // stagger led lights just cause

   reg [15:0] counter;
    reg [15:0] counter1;

    initial begin 
    counter1 = 0;
    counter = 0;
    end

    //use counter to have a 1ms or 2ms or 1.5ms duty cycle for a while inorder to actually run
    //because run it this way is asking the servo to move for 1.5ms so it cant atually move that fast

    always @ (posedge M_CLOCK)
    begin
   counter <= counter+1;
    counter1 <= counter1+1;
    end


    always @ (negedge M_CLOCK)
    begin

            //if (counter1 > 500) 
            //begin
            SERVOPWM <= (counter <= 1);
            //end

    end



endmodule

Currently, I can get it to turn all the way to the right, no matter whether I send it 2ms or 1ms. The big problem I'm having is trying to get it to operate ONLY to turn to the right, and then stop. Everything I've tried ends up in it either not working at all, or working nonstop like I never had a 0 sent to the pin in the first place.

Can anyone suggest the best way to send it a 0 after enough time to rotate all the way to one direction?

Thanks!

Cody Friszell
  • 27
  • 1
  • 8

1 Answers1

0

You need to adjust the voltage to servo by pulse width modulation (PWM). In other words if you want 10% voltage you need to set your outpin SERVOPWM 10 percent of the duration.

The way I'd do is like:

module ServoTestNShit(input M_CLOCK,

                             input  [7:0] voltage_percentage,
                             output [7:0] IO_LED, // IO Board LEDs
                             output reg SERVOPWM);    
   reg [7:0] counter;


    initial begin 

    counter = 0;
    end

    // let the counter count for 100 time units
    always @ (posedge M_CLOCK)
    begin
         counter <= counter+1;
         if (counter <= 100)
            counter <= 0;
    end

    // set the output 1 for voltage_percentage/100 of the time
    always @ (negedge M_CLOCK)
    begin
            SERVOPWM <= (counter <= voltage_percentage);
    end



endmodule
Alper Kucukkomurler
  • 1,706
  • 2
  • 13
  • 19
  • I'm confused. I don't see how that would help, as if i change voltage_percentage to be, say, 10, it won't ever set the pin as high for a correct amount of time, therefore never actually setting the pin, leaving the servo motionless. Additionally, why do we set servo = counter = voltage_percentage? What's the idea behind setting all three equal? – Cody Friszell Dec 14 '16 at 06:30
  • No, we are not setting all of them equal. `(counter <= voltage_percentage)` is comparison (larger than or equal to). In other words you can think like if (counter <= voltage_percentage) – Alper Kucukkomurler Dec 14 '16 at 07:44
  • `if (counter <= voltage_percentage) SERVOPWM <= 1; else SERVOPWM <= 0;` – Alper Kucukkomurler Dec 14 '16 at 08:14
  • interesting. So what makes it differ between being a nonblocking statement and the comparison? – Cody Friszell Dec 14 '16 at 19:10
  • I would agree on that the language has a confusing point here. Bu the only place you'll use a nonblocking assignment is inside an always block. Pretty much all the other uses are comparisons. – Alper Kucukkomurler Dec 15 '16 at 11:24