Sygall
Sygall

Reputation: 33

Can't make servomotors move with a Jetson card

I have a Arducam IMX477 12MP PTZ Camera that I am trying to control with my Jetson AGX Orin developer kit. For now, I am focused on controlling the servomotors -- I will take care of the video acquisition later.

I have connected all cables to my Jetson card just like it is indicated in this tutorial. I also have connected the Servo Vcc cable to a 5V (1A) pin on my Jetson card. The I2C connection is working as I can detect the correct address with i2cdetect -r -y 7. Also, when I am trying to move my servo using the given code (see below), I can see a LED blinking on the PTZ support. However, the servomotors are not moving

I have checked several times the hardware setup and everything looks good. I am kind of running out of idea in term of what might not be working, which is the reason I am kindly asking for your help right now.

Here is the code I am using:

Focuser.py

import sys
import time
import smbus

import fcntl
import os
import struct


class Focuser:
    bus = None
    CHIP_I2C_ADDR = 0x0C
    BUSY_REG_ADDR = 0x04
    
    starting_point =     [
        10000, 10000, 10000, 
        10720, 8070, 5970, 
        4320, 2920, 1920, 
        970, 520, 20, 0, 
        0, 0, 0, 0, 0, 0, 
        0, 0
    ]

    end_point = [
        20000, 20000, 20000, 
        20000, 19620, 17020, 
        14920, 13170, 12020, 
        10970, 10170, 9770, 
        9170, 9020, 8820, 
        8570, 8570, 8570, 
        8770, 8970, 9170
    ]

    
    OPT_BASE    = 0x1000
    OPT_FOCUS   = OPT_BASE | 0x01
    OPT_ZOOM    = OPT_BASE | 0x02
    OPT_MOTOR_X = OPT_BASE | 0x03
    OPT_MOTOR_Y = OPT_BASE | 0x04
    OPT_IRCUT   = OPT_BASE | 0x05
    opts = {
        OPT_FOCUS : {
            "REG_ADDR" : 0x01,
            "MIN_VALUE": 0,
            "MAX_VALUE": 20000,
            "RESET_ADDR": 0x01 + 0x0A,
        },
        OPT_ZOOM  : {
            "REG_ADDR" : 0x00,
            "MIN_VALUE": 3000,
            "MAX_VALUE": 20000,
            "RESET_ADDR": 0x00 + 0x0A,
        },
        OPT_MOTOR_X : {
            "REG_ADDR" : 0x05,
            "MIN_VALUE": 0,
            "MAX_VALUE": 180,
            "RESET_ADDR": None,
        },
        OPT_MOTOR_Y : {
            "REG_ADDR" : 0x06,
            "MIN_VALUE": 0,
            "MAX_VALUE": 180,
            "RESET_ADDR": None,
        },
        OPT_IRCUT : {
            "REG_ADDR" : 0x0C, 
            "MIN_VALUE": 0x00,
            "MAX_VALUE": 0x01,   #0x0001 open, 0x0000 close
            "RESET_ADDR": None,
        }
    }


    def __init__(self, bus):        
        try:
            self.bus = smbus.SMBus(bus)
        except:
            print("init focuser failed")
            sys.exit(0)
        
    def read(self,chip_addr,reg_addr):
        value = self.bus.read_word_data(chip_addr,reg_addr)
        value = ((value & 0x00FF)<< 8) | ((value & 0xFF00) >> 8)
        return value
    
    def write(self,chip_addr,reg_addr,value):
        if value < 0:
            value = 0
        value = ((value & 0x00FF)<< 8) | ((value & 0xFF00) >> 8)
        return self.bus.write_word_data(chip_addr,reg_addr,value)

    def get(self,opt,flag = 0):
        self.waitingForFree()
        info = self.opts[opt]
        return self.read(self.CHIP_I2C_ADDR,info["REG_ADDR"])

    def set(self,opt,value,flag = 1):
        self.waitingForFree()
        info = self.opts[opt]
        if value > info["MAX_VALUE"]:
            value = info["MAX_VALUE"]
        elif value < info["MIN_VALUE"]:
            value = info["MIN_VALUE"]
        self.write(self.CHIP_I2C_ADDR,info["REG_ADDR"],value)
        if flag & 0x01 != 0:
            self.waitingForFree()
    
    def isBusy(self):
        return self.read(self.CHIP_I2C_ADDR,self.BUSY_REG_ADDR) != 0
    
    def waitingForFree(self):
        count = 0
        begin = time.time()
        while self.isBusy() and count < (5 / 0.01):
            count += 1
            time.sleep(0.01)
    
    def reset(self,opt,flag = 1):
        self.waitingForFree()
        info = self.opts[opt]
        if info == None or info["RESET_ADDR"] == None:
            return
        self.write(self.CHIP_I2C_ADDR,info["RESET_ADDR"],0x0000)
        self.set(opt,info["MIN_VALUE"])
        if flag & 0x01 != 0:
            self.waitingForFree()

MotorController (main script)

import cv2
import numpy as py
import os
import sys
import time
import argparse
from JetsonCamera import Camera
import pygame

from Focuser import Focuser
import curses

global image_count
image_count = 0

def parse_cmdline():
    parser = argparse.ArgumentParser(description='Arducam Controller.')

    parser.add_argument('-i', '--i2c-bus', type=int, nargs=None, required=True,
                        help='Set i2c bus, for A02 is 6, for B01 is 7 or 8, for Jetson Xavier NX it is 9 and 10.')

    return parser.parse_args()


motor_step  = 5
        
args = parse_cmdline()

focuser = Focuser(args.i2c_bus)

clock = pygame.time.Clock()
fps = 20


pygame.init()

screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Détection de touches")

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_q:
                running = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_w]:
        focuser.set(Focuser.OPT_MOTOR_Y, focuser.get(Focuser.OPT_MOTOR_Y) - motor_step)
    if keys[pygame.K_a]:
        focuser.set(Focuser.OPT_MOTOR_X, focuser.get(Focuser.OPT_MOTOR_X) + motor_step)
    if keys[pygame.K_s]:
        focuser.set(Focuser.OPT_MOTOR_Y, focuser.get(Focuser.OPT_MOTOR_Y) + motor_step)
    if keys[pygame.K_d]:
        focuser.set(Focuser.OPT_MOTOR_X, focuser.get(Focuser.OPT_MOTOR_X) - motor_step)

    clock.tick(fps)
    
pygame.quit()
sys.exit()

P.-S: the servomotors used for the PT Camera support are DS3115mg

Upvotes: 0

Views: 52

Answers (0)

Related Questions