2007年4月21日 星期六

ATmega-128 的 16-Channels PWM 輸出(二)


新增了 delay 部份後,情況得以改善。下一步便是鋰電了!要找 Dr.Victor 老師幫忙!

以下是我的原碼:

//=============================================//
// Robot Amigo Main Program - Ver.2.00 //
// Copyright Pacess HO, 2007. //
// File : Amigo.c //
// Platform : ATmega-128 (BestTechnology) //
// Last update : 21-April-2007 //
//=============================================//

// History:
// 1.00 - Control 4 servos at the same time
// 1.10 - Fix counter bug on 1.00
// - Can control 4 servos now
// - Use PB as LED output ports
// 1.20 - Try to control 8 servos at the same time by setting TIMER-1 from 5ms to 2.5ms
// 2.00 - Use new technology to control over 8 servos at the same time

// PULSE SIGNAL:
// __
// | | Pulse width = 0.6ms = Left most
// __| |_____...
// ___
// | | Pulse width = 1.5ms = Center
// __| |____...
// ____
// | | Pulse width = 2.4ms = Right most
// __| |___...

// TIMER 0: Signal pulse width control
// __
// | |
// ___| |____________...

// TIMER 1: Generate a signal every 5ms (4 signals within 20ms)
// __ __ __
// | | | | | |
// ___| |__| |__| |__...

// TIMER 2: Use for time counter
// /| /| /| /|
// / | / | / | / |
// / |/ |/ |/ |....

#include < avr/io.h >
#include < avr/interrupt.h >
#include < rs.h >

#define SERVO_MAX 16

//====================//
// Global variables //
//====================//
char pTransfer[10], pReceive[10]; // RS-232 data buffers

// From real measurement:
// Value 20 = 1481us
// Value 21 = 1543us
// Value 34 = 2272us
char g_pServoData[16] = { // Current position of servos
35, 34, 34, 33, 21, 21, 20, 21, // Value from 8.2 -> 20.5 -> 32.8
35, 34, 34, 33, 21, 21, 20, 21};
char g_pServoLast[16] = { // Last position of servos
35, 34, 34, 33, 21, 21, 20, 21, // Value from 8.2 -> 20.5 -> 32.8
35, 34, 34, 33, 21, 21, 20, 21};
char g_pServoNext[16] = { // Next position of servos
1, 1, 1, 1, 1, 1, 1, 1, // Value from 8.2 -> 20.5 -> 32.8
1, 1, 1, 1, 1, 1, 1, 1};
unsigned char g_iCurrentStep, g_iTotalStep;
int iLED = 0;

//=============================================================================
// Servo pulse output
//=============================================================================
void ServoOut(unsigned char *pServoData, int iLoop) {
unsigned int iPortData;
int iChannel;

// The following while loop takes 73us for 1 loop when SERVO_MAX = 16 //
while (iLoop > 0) {
iPortData = 0;
for (iChannel=0; iChannel < SERVO_MAX; iChannel++) {

// Set bit on/off of each channel //
iPortData = ((iPortData<<1) | (pServoData[iChannel] >= iLoop));
}

// Output to PA0~PA7 and PC0~PC7 //
PORTA = (unsigned char)(iPortData&0xff);
PORTC = (unsigned char)((iPortData>>8)&0xff);

iLoop--;
}

// Set PA0~PA7 and PC0~PC7 to LOW(0) //
PORTA = 0x00;
PORTC = 0x00;
}

//==================================//
// Wait for specified mini second //
//==================================//
void wait_ms(int iMSecond) {
int iCount;

TCCR2 |= ((1 << CS21)|(1 << CS20)); // Counter 2 / 64 section

for (iCount=0; iCount < iMSecond; iCount++) {
TCNT2 = 0x00; // Clear counter 2
while (TCNT2 < 250); // Wait for 1 mini second
}
}

//======================================//
// Counter 1 (8-bits) match interrupt //
//======================================//
SIGNAL(SIG_OUTPUT_COMPARE1A) {
// From real measurement:
// Loop 10 = 730us, thus loop 35 = 2555us = 2.555ms
// Loop 35 = 2760us
TCNT1 = 0x00; // Clear counter 1
ServoOut(g_pServoData, 30);
}

//=============================================================================
// Update servos position
//=============================================================================
void UpdateAllServo(void) {
char i;

for (i=0; i < SERVO_MAX; i++) {
g_pServoData[i] += g_pServoNext[i];
if (g_pServoData[i] == 21) {g_pServoNext[i] = 1;}
if (g_pServoData[i] == 34) {g_pServoNext[i] = -1;}
}
}

//=====================//
// Main program flow //
//=====================//
void main(void) {
int iLED, iCount, i;

//--------------------------//
// Init. system variables //
//--------------------------//
g_iTotalStep = 13;
g_iCurrentStep = g_iTotalStep;

// Set PA0~PA7 and PC0~PC7 as OUTPUT port //
DDRA = 0xff;
DDRC = 0xff;

// Set PA0~PA7 and PC0~PC7 to LOW(0) //
PORTA = 0x00;
PORTC = 0x00;

// Set PB0~7 LED as OUTPUT port //
DDRB = 0xff;
PORTB = 0x00;

// Counter 1 setup //
TIMSK |= (1 << OCIE1A); // Enable compare A interrupt
TCCR1A |= (1 << WGM12); // Set counter 1 to CTC mode
OCR1A = 40000; // 40000 / 8 section = 20ms

// Initialize COM port and baud rate 115200 bps //
rs0_init(br115200, pTransfer, sizeof(pTransfer), pReceive, sizeof(pReceive));
fdevopen(rs0_putchar, rs0_getchar);

// Enable interrupt //
SREG |= (1 << SREG_I);
TCCR1B |= (1 << CS11);

// Display connecting message //
rs0_puts("========================================\n");
rs0_puts("== AMIGO-003 Ver 2.00.070421-67 ==\n");
rs0_puts("== Copyrights Pacess HO, 2006-2007. ==\n");
rs0_puts("========================================\n\n");

iLED = (0-1);
while(1) {
// Set PB0~7 LED on and off //
iLED = (iLED+1)&7;
PORTB = ~(1 << iLED);

// Update position of all servos //
UpdateAllServo();

for (iCount=0; iCount < 1000; iCount++) {
for (i=0; i < 100; i++) {
PORTB = PORTB;
}
}
}
}

沒有留言: