Search code examples
verilogfpgaservo

Servo won't stop on a FPGA


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!


Solution

  • 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