我从微控制器开始,我正在尝试编写连接到Atmega32(带外部时钟)微控制器的太阳能电池板的电压测量。太阳能电池板安装在步进电机上,可以使太阳能电池板旋转。
这是我的代码的一部分(可编译):
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#define B_0000 0
#define B_0001 1
#define B_0010 2
#define B_0011 3
#define B_0100 4
#define B_0101 5
#define B_0110 6
#define B_0111 7
#define B_1000 8
#define B_1001 9
#define B_1010 a
#define B_1011 b
#define B_1100 c
#define B_1101 d
#define B_1110 e
#define B_1111 f
#define _B2H(bits) B_##bits
#define B2H(bits) _B2H(bits)
#define _HEX(n) 0x##n
#define HEX(n) _HEX(n)
#define _CCAT(a,b) a##b
#define CCAT(a,b) _CCAT(a,b)
#define BYTE(a,b) HEX( CCAT(B2H(a),B2H(b)) )
#define STEPMOTOR_PORT PORTC
#define SOLAR_INPUT_PIN (1<<MUX2)|(1<<MUX0)
#define STEPMOTOR_STEP 8 // length of one step motor full step
#define STEPMOTOR_YZ_MAX_POSITION 6 // max stepmotor cw position
#define STEPMOTOR_YZ_MIN_POSITION -6 //max stepmotor ccw position
/* counterclockwise */
void inline stepmotor_yz_ccw_step()
{
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0000, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0001, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0011, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0010, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0110, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0100, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(1100, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(1000, 0000);
_delay_us(10000);
}
/* clockwise */
void inline stepmotor_yz_cw_step()
{
_delay_us(10000);
STEPMOTOR_PORT = BYTE(1000, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(1100, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0100, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0110, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0010, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0011, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0001, 0000);
_delay_us(10000);
STEPMOTOR_PORT = BYTE(0000, 0000);
_delay_us(10000);
}
unsigned int inline measure_voltage()
{
ADCSRA |= (1 << ADSC); // Start conversion
while (ADCSRA & (1 << ADSC)) ; // wait for conversion to complete
return ADCW;
}
void inline ports_init()
{
DDRD = BYTE(1111, 1111);
DDRC = BYTE(1111, 1111);
PORTD = BYTE(1111, 1111);
PORTC = BYTE(0000, 0000);
}
/* single measurement, ref voltage is 5V, division factor 32, PA5 port */
void inline adc_init()
{
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS0);
ADMUX = SOLAR_INPUT_PIN;
ADMUX |= (1 << REFS0);
}
/* light led according to measured voltage */
void inline light_leds(unsigned int voltage)
{
if (voltage < 128) {
PORTD = BYTE(1111, 1110);
}
if (voltage > 128 && voltage < 256) {
PORTD = BYTE(1111, 1101);
}
if (voltage > 256 && voltage < 384) {
PORTD = BYTE(1111, 1011);
}
if (voltage > 384 && voltage < 512) {
PORTD = BYTE(1111, 0111);
}
if (voltage > 512 && voltage < 640) {
PORTD = BYTE(1110, 1111);
}
if (voltage > 640 && voltage < 768) {
PORTD = BYTE(1101, 1111);
}
if (voltage > 768 && voltage < 896) {
PORTD = BYTE(1011, 1111);
}
if (voltage > 896 && voltage < 1024) {
PORTD = BYTE(0111, 1111);
}
}
int main(void)
{
unsigned int current_voltage = 0;
unsigned int max_voltage = 0;
int max_position = 0;
int current_position = 0;
int i = 0;
ports_init();
adc_init();
while (1) {
/* if not too far */
if (current_position < STEPMOTOR_YZ_MAX_POSITION) {
for (i = 0; i < STEPMOTOR_STEP; ++i)
stepmotor_yz_cw_step();
current_position++;
}
_delay_ms(5000);
current_voltage = measure_voltage();
if (current_voltage > max_voltage)
{
max_voltage = current_voltage;
max_position = current_position;
light_leds(max_voltage);
}
}
}
问题在于,电压测量和步进电机旋转分开工作。即使是两步电机的旋转也能工作。 ADC本身也可以点亮LED,如上面的最大电压,或者例如每次测量后的电流电压。但当我将这两者混合在一起时,一切都会停止。
当我像上面那样把它们放在一起时,我认为&#34;太远&#34;如果因为步进电机没有移动甚至没有检查,也没有发生电压测量。
当我将current_position设置为volatile时,步进电机会按预期开始旋转,但它永远不会停止,就像current_position根本没有增加一样。在那种情况下,adc测量不起作用。
Programator是FT232R Bitbang。
我正在使用这个stepmotor和驱动程序: http://www.instructables.com/id/BYJ48-Stepper-Motor/
太阳能电池板的电压为0-5V
我正在使用入门套件测试它(英文版可以通过页面顶部的图标打开): http://and-tech.pl/zestaw-evb-5-1/
生成文件:
F_CPU=16000000
CC=avr-gcc
CFLAGS=-mmcu=atmega32 -Wall -O2 -DF_CPU=$(F_CPU) -gstabs -ffunction-sections -fdata-sections
CXX=avr-g++
CXXFLAGS=$(CFLAGS)
OBJCOPY=avr-objcopy
AVRDUDE = -c ft232r -p m32 -P ft0 -B 19200 -U flash:w:"program.hex":a
program: main.o
$(CXX) -o program main.o -I.
main.o: main.c
$(CXX) $(CXXFLAGS) -c main.c -I.
hex: program
$(OBJCOPY) -O ihex program program.hex
upload: hex
avrdude $(AVRDUDE)
clean:
rm -f *.hex *.o *.s *.hex
我想这是一个代码问题,而不是硬件,因为我在两个不同的Atmega32微控制器上测试它,以确保一切正常。
提前感谢您的帮助!
Br,ruker