Como controlar 2 servomotores con el microchip Atmega16a

good day. I am working on a project with the ATmega16A where I am trying to control 2 servomotors to maintain the balance of a tray. The problem is that the servos work individually to maintain balance, but when I connect the 2 servos, they stop working. I wanted to see if anyone knows how to make them work together.

para controlar bien servo X

#define F_CPU 1000000UL

#include <avr/io.h>

#include <util/delay.h>

#include <stdio.h>

#include “lcd.h”

// Definición de pines para el sensor ADXL335

#define xpin 1 // ADC1 en ATmega16 (ADC1 en PA1)

#define ypin 2 // ADC2 en ATmega16 (ADC2 en PA2)

// Definición de pines para los servos MG90S

#define servoX_pin PB5 // Puerto B, pin 5 para control del servo X (OC1A)

#define servoY_pin PB3 // Puerto B, pin 3 para control del servo Y (OC0)

char buffer[16];

uint16_t last_x_val = 0; // Variable para almacenar la última lectura estable del ADC para el eje X

uint16_t last_y_val = 0; // Variable para almacenar la última lectura estable del ADC para el eje Y

// Función para mapear valores de una escala a otra

int16_t map(int16_t x, int16_t in_min, int16_t in_max, int16_t out_min, int16_t out_max) {

return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;

}

void setup() {

DDRA = 0x00;  // Puerto A como entrada para los pines del ADC

DDRB |= (1 << servoX_pin) | (1 << servoY_pin);  // Pines de los servos como salida

lcd_init(LCD_DISP_ON);  // Inicializar LCD

}

void setupADC() {

ADMUX = (1 << REFS0);  // Referencia de voltaje a AVCC con capacitor externo

ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0);  // Habilitar ADC y configurar prescaler a 8

}

uint16_t ADC_read(uint8_t chan) {

ADMUX = (ADMUX & 0xF8) | (chan & 0x07);  // Seleccionar canal

ADCSRA |= (1 << ADSC);  // Iniciar la conversión

while (ADCSRA & (1 << ADSC));  // Esperar a que termine la conversión

return ADC;  // Devolver el valor leído

}

void controlServoX(uint16_t x_val) {

// Definir una pequeña banda de histeresis para evitar ajustes innecesarios

int16_t hysteresis_min = -3;

int16_t hysteresis_max = 3;



// Comparar la nueva lectura del ADC con la última lectura estable

if (x_val < last_x_val + hysteresis_max && x_val > last_x_val - hysteresis_min) {

    // Si la diferencia es menor que la histeresis, mantener la última posición del servo X

    return;

}



// Actualizar la última lectura estable del ADC para el eje X

last_x_val = x_val;



// Definir los valores mínimos y máximos del ADC para los ángulos de servo correspondientes para el eje X

uint16_t min_adc = 270;

uint16_t max_adc = 410;



// Definir los ángulos correspondientes a los valores del ADC para el servo X

int16_t min_angle = -90;

int16_t max_angle = 90;



// Mapear el valor del ADC al rango de ángulos para el servo X

int16_t angle = map(x_val, min_adc, max_adc, max_angle, min_angle);



// Convertir el ángulo a un valor adecuado para el servo X (6 a 34 para el PWM)

uint8_t pwm_value = map(angle, min_angle, max_angle, 6, 34);



// Configurar el PWM para el servo X (OCR0)

if (OCR0 < pwm_value) {

    for (uint8_t i = OCR0; i <= pwm_value; ++i) {

        OCR0 = i;

        _delay_ms(5);  // Pequeño retraso para el movimiento suave

    }

    } else {

    for (uint8_t i = OCR0; i >= pwm_value; --i) {

        OCR0 = i;

        _delay_ms(5);  // Pequeño retraso para el movimiento suave

    }

}

}

void controlServoY(uint16_t y_val) {

// Definir una pequeña banda de histeresis para evitar ajustes innecesarios

int16_t hysteresis_min = -3;

int16_t hysteresis_max = 3;



// Comparar la nueva lectura del ADC con la última lectura estable

if (y_val < last_y_val + hysteresis_max && y_val > last_y_val - hysteresis_min) {

    // Si la diferencia es menor que la histeresis, mantener la última posición del servo Y

    return;

}



// Actualizar la última lectura estable del ADC para el eje Y

last_y_val = y_val;



// Definir los valores mínimos y máximos del ADC para los ángulos de servo correspondientes para el eje Y

uint16_t min_adc = 270;

uint16_t max_adc = 410;



// Definir los ángulos correspondientes a los valores del ADC para el servo Y

int16_t min_angle = -90;

int16_t max_angle = 90;



// Mapear el valor del ADC al rango de ángulos para el servo Y

int16_t angle = map(y_val, min_adc, max_adc, max_angle, min_angle);



// Convertir el ángulo a un valor adecuado para el servo Y (6 a 34 para el PWM)

uint8_t pwm_value = map(angle, min_angle, max_angle, 6, 34);



// Configurar el PWM para el servo Y (OCR1A)

if (OCR1A < pwm_value) {

    for (uint8_t i = OCR1A; i <= pwm_value; ++i) {

        OCR1A = i;

        _delay_ms(5);  // Pequeño retraso para el movimiento suave

    }

    } else {

    for (uint8_t i = OCR1A; i >= pwm_value; --i) {

        OCR1A = i;

        _delay_ms(5);  // Pequeño retraso para el movimiento suave

    }

}

}

void Impresion(uint16_t x_val, uint16_t y_val) {

// Mostrar valores en el LCD

lcd_gotoxy(0, 0);

sprintf(buffer, "X: %u", x_val);  // Mostrar valor de ADC para X

lcd_puts(buffer);



lcd_gotoxy(0, 1);

sprintf(buffer, "Y: %u", y_val);  // Mostrar valor de ADC para Y

lcd_puts(buffer);

}

int main(void) {

setup();

setupADC();



// Configuración del timer para el servo Y (Timer0, PB3, OCR0)

TCCR0 = (1 << WGM00) | (1 << WGM01) | (1 << COM01) | (1 << CS01) | (1 << CS00);  // Set Fast PWM, Clear OC0 on compare match, Prescaler de 64

OCR0 = 20;  // Valor inicial del PWM para el servo Y



// Configuración del timer para el servo X (Timer1, PB5, OCR1A)

TCCR1A = (1 << WGM10) | (1 << COM1A1);  // Set Fast PWM, Clear OC1A on compare match

TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10);  // Prescaler de 64

ICR1 = 4999;  // Frecuencia de PWM: 50 Hz

OCR1A = 20;  // Valor inicial del PWM para el servo X



while (1) {

    // Leer valores ADC de los pines asignados

    uint16_t x_val = ADC_read(xpin);  // Lee el ADC1 (PA1) para el eje X

    uint16_t y_val = ADC_read(ypin);  // Lee el ADC2 (PA2) para el eje Y



    // Controlar el servo X basado en el valor del ADC

    controlServoX(x_val);



    // Controlar el servo Y basado en el valor del ADC

    controlServoY(y_val);



    // Mostrar los valores en el LCD durante el movimiento

    Impresion(x_val, y_val);

    _delay_ms(20);  // Pequeño retraso entre cada ajuste más corto para movimiento más suave



    // Mostrar los valores finales en el LCD después del movimiento completo

    Impresion(x_val, y_val);

    _delay_ms(200);  // Esperar una fracción de segundo entre cada lectura completa del ADC

}



return 0;

}

New contributor

Jorge M is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật