Стенд «АЦП/ШИМ»

 

Стенд представляет собой управляемый двухканальный генератор сигналов ШИМ с управляемой скважностью.

Стенд предназначен для изучения принципов работы АЦП и методов генерации сигналов ШИМ. Стенд может применяться для проведения практических занятий в рамках курсов «Знакомство с микроконтроллерами и интегральной схемотехникой», «Спортивная робототехника» и аналогичных.

 

Контроллер стенда построен на основе ATMega8. В состав стенда, помимо контроллера, входят: согласующий узел (токовый усилитель) и органы управления – переменные резисторы, определяющие скважность сигнала ШИМ.

 

 

Выходными сигналами являются 2 канала ШИМ-управления. Управляющий интерфейс соответствует стандартному интерфейсу сервоприводов – рулевых машинок («сигнал» - «+» - «земля»).

 

Принцип работы

Напряжение, снимаемое с переменных резисторов, поступает на входы усилителей. Далее усиленные сигналы поступают на входы АЦП. Исходя из значений сигналов вычисляются параметры выходных ШИМ-сигналов.

Выходной управляющий сигнал представляет собой последовательность прямоугольных импульсов с амплитудой 5 В и длительностью от 0.9 до 2.1 мс. Импульсы следуют с частотой 50 Гц. При ширине импульса 1 мс шток рулевой машинки разворачивается в крайнее левое положение; при ширине импульса в 1.5 мс шток занимает центральное положение, а при ширине в 2 мс - крайнее правое положение.

Сигнал управления

Программная реализация

Для генерации сигналов контроллер использует т.н. аппаратный ШИМ (или PWM), реализованный на таймере Timer1. Выходные ШИМ-сигналы снимаются с выводов PORB.1 и PORTB.2 микроконтроллера ATMega8.

Для переопределения выводов PORB.1 и PORTB.2, а также для настройки Таймера 1 используется функция InitPWM, а для установки параметров ШИМ-сигнала на выводах B.1 и B.2 используется функция PWMSetAng().

 

void InitPWM(void) - Инициализация аппаратного ШИМа (PWM)

void PWMSetAng(A,B) - Установить значения ШИМ для OC1A и OC1B (PORTB.1 и PORTB.2), соответствующие углам поворота сервомашинок A и B. Значения A и B указываются в градусах: от -60 до 60.

Текст основной программы приведен в конце.

Токовый усилитель

Для корректного измерения напряжения требуется, чтобы выходное сопротивление схемы, с которой снимается напряжение, было мало - несколько десятков килоОм. Это связано с особенностями реализации АЦП. Поэтому рекомендуется использовать усилитель (эмиттерный повторитель), схема которого приведена ниже.

Переменный резистор R1 определяет величину выдаваемого напряжения (от 0 до значения, близкого к напряжению питания).

Вычисление угла поворота A сервомашинки по заданному напряжению U осуществляется следующим образом:

A = U* (Amax-Amin) / Umax + Amin

Здесь Amax, Amin – максимальный и минимальный угол поворота сервомашинки соответственно (+60° - -60°), Umax – максимальное (верхнее) значение измеряемого напряжения.

 

Текст основной программы

/*****************************************************

Project : M8k

Генератор ШИМ на 2 канала (режим PWM, B.1, B2)

 

Chip type           : ATmega8

Program type        : Application

Clock frequency     : 7,372800 MHz

Memory model        : Small

External SRAM size  : 0

Data Stack size     : 256

*****************************************************/

 

#include <mega8.h>

#include <stdio.h>

#include <delay.h>

#include <sleep.h>

#include "m8lib.h"

#include "pwm8lib.h"

 

char *Title = "\r\nPWM GEN 2.01\r\n\r\n";

 

#define cmdIndic ef_7

 

//----------------------------------------------------------

 

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

// Рабочий таймер (500 Hz)

{

  TCNT0=TCNT0_RESET_VAL;

  if(TICK_CNT0%2) cmdIndic=1; else cmdIndic=0;

  TICK_CNT0++;

}

 

interrupt [TIM2_OVF] void timer2_ovf_isr(void) { }

// Рабочий таймер (50 kHz)

 

//----------------------------------------------------------

 

int U2Ang(float U)

// Преобразование напряжения в угол: 0 - MinAng, ADCUMAX - MaxAng

{

  int dS, S;

  float dU;

  dS = MaxAng-MinAng;

  dU = ADCUMAX;

  S = U*dS/dU + MinAng;

  if(S<MinAng) S = MinAng;

  if(S>MaxAng) S = MaxAng;

  return S;

}

 

void main(void)

{

  float r1, r2;

  int V1, V2, V1_pred, V2_pred;

  char wasCh;

 

  InitCM8();

 

  InitPWM(); // Инициализация аппаратного ШИМа (PWM)

 

  InitADC(ADCE5);

 

  printf("%s",Title);

 

  PWMSetAng(0,0);

 

  ADCUMAX = 4.8;

 

  V1_pred = V2_pred = -1;

 

  while(1)

  {

    r1 = ReadADC(ADC1);

    V1 = U2Ang(r1);

    r2 = ReadADC(ADC2);

    V2 = U2Ang(r2);

    printf("%4.2f %3d  %4.2f %3d\r", r1, V1, r2, V2);

    wasCh = 0;

    if(V1!=V1_pred)

    {

      wasCh = 1;

      V1_pred = V1;

    }

    if(V2!=V2_pred)

    {

      wasCh = 1;

      V2_pred = V2;

    }

    if(wasCh)

      PWMSetAng(V1,V2);

  }

}