将代码从 ATmega32 修改为 Arduino Mega - 函数“main”中出现错误即使没有

发布于 2024-08-16 21:58:12 字数 14490 浏览 5 评论 0原文

我正在尝试修改此代码,以使其在 Arduino Mega 上运行。我对 C 还很陌生,所以我可能犯了一些重大错误。顺便说一下,这是一个自平衡滑板。

此代码取自 ATmega32(来自 这里,我试图让它在 Arduino Mega)。

此代码是为 ATmega32 开发板编写的。

但我遇到这个错误:

o:在函数main'中:
C:\Users\********\AppData\Local\Temp\build27006.tmp/Test2.cpp:406:
未定义的引用
设置'

怎么会这样?我在这里甚至没有对 setup 的引用!

这是我的代码:

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <math.h>

#define CLOCK_SPEED  16000000
#define OCR1_MAX   1023

typedef unsigned char u8;
void set_motor_idle(void);
void InitPorts(void);
float level = 0;
float Throttle_pedal;
float aa;
float accelraw;
float x_acc;
float accsum;
float x_accdeg;

float gyrosum;

float gangleratedeg;
float gangleraterads;
float ti = 2.2;

float overallgain;
float gaincontrol;
float batteryvolts = 24;
float gyroangledt;
float angle;
float anglerads;
float balance_torque;
float softstart;

float cur_speed;
float cycle_time = 0.0064;
float Balance_point;
float a0, a1, a2, a3, a4, a5, a6; //Savitzky-Golay variables for accelerometer.

float TCCR0;

int i;
int j;
int tipstart;

void InitPorts(void)
{
    PORTC = 0x00;  //Port C pullups set to low (no output voltage) to begin with.
    DDRC = 0xFF; //Port C pins all set as output via the port C direction register.
    //PORTC |= (1<<PC1); //Make C1 +ve so disables OSMC during startup.

    DDRA = 0x00; //All port A pins set as input.
    PORTA = 0x00; //Port A input pullups set to low pullups.

    DDRD = 0xFF; //Configure all port D pins as output as prerequisite
               //for OCR1A (PinD5) and OCR1B (Pin D4) working properly.

    PORTB = 0x00;  //Port B pullups set to low (no output voltage) to begin with.
    DDRB = 0xFF; //All port B pins set to output.
}

/*
  IO:

  I am using a ATMega32 16 MHz with an external crystal clock. New planned pin
  arrangement to OSMC motor controller.

    PC4        Onboard LED
    PD5/OC1A   ALI -> OSMC pin 6
    PD4/OC1B   BLI -> OSMC pin 8
    PC1        Disable -> OSMC pin 4
    PC2        BHI -> OSMC pin 7
    PC3        AHI -> OSMC pin 5
    PA6/ADC6   Vbatt/10 -> OSMC pin 3
    PA1/ADC1   pitch rate gyro
    PA0/ADC0   accelerometer
*/

void adc_init(void) {
    /* Turn off analogue comparator as we don't use it */
    ACSR = (1 << ACD);

    /* Select PA0 */
    ADMUX = 0;
    ADMUX |=(1<<REFS0); //This tells it to use VCC (approx. 5 V) as the reference
                        //voltage NOT the default which is the internal 2.5V reference
    /* Set ADC prescaler to 128, enable ADC, and start conversion. */
    ADCSRA = 0 | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
               | (1<<ADEN)  //Enable ADC
               | (1<<ADSC); //Start first conversion
    /* Wait until bogus first conversion is finished */
    while (ADCSRA & (1 << ADSC)) {
    }
}


uint16_t adc_read(uint8_t channel) {
    /* Select channel */
    ADMUX = channel;
    ADMUX |= (1<<REFS0); //Here it is again
    /* Start conversion */
    ADCSRA |= (1 << ADSC);
    /* Wait until conversion finished */
    while (ADCSRA & (1 << ADSC)) {
    }
    /* Return the result */
    return ADCW;
}

/* 156 cycles per sec, 6.4 ms per cycle MEASURED ON OSCILLOSCOPE. */
/* Read all the ADC inputs and do some conversion. */
void sample_inputs(void) {
    uint16_t adc0, adc1, adc2, adc3, adc4, adc5;

    gyrosum = 0;
    adc0 = adc_read(0); /* Accelerometer pin PA0 */
    accelraw = (float) adc0;

    for (j=0; j<7; j++) {
        adc1 = adc_read(1); //Gyro pin PA1
        gyrosum = (float) gyrosum + adc1; //Using a mean of 7 samples per loop for the gyro so
                                          //it gets a complete update with each loop of the program.
    }

    adc2 = adc_read(2); /* Grey wire overallgain (via cutout switch), position PA2. */
    adc3 = adc_read(3); /* Position lever pulled back position PA3. */
    adc4 = adc_read(4); /* Throttle_pedal, position PA4. */
    adc5 = adc_read(5); /* Position lever pushed forwards, position PA5. */
    //adc6 = adc_read(6); /* Vbatt input from OSMC (not used at present), position PA6. */

    //Sav Golay filter for accelerometer only.
    a0 = a1;
    a1 = a2;
    a2 = a3;
    a3 = a4;
    a4 = a5;
    a5 = a6;
    a6 = (float) accelraw;
    accsum = (float) ((-2*a0) + (3*a1) + (6*a2) + (7*a3) +
                      (6*a4) + (3*a5) + (-2*a6))/21;  //Sav Golay calculation

    gaincontrol = (float) gaincontrol*0.9 + 0.1*adc2/341; //Smooths any voltage spikes and gives range 0-3.

    Throttle_pedal=(float) Throttle_pedal*0.9 + 0.1*adc4/341; //Smooths any voltage spikes and gives range 0-3

    //Cuts the motor if the dead mans button is let go
    //(gaincontrol variable also wired in through this button to adc2
    if (adc2<100) {
        Throttle_pedal = 0.001;
        gaincontrol = 0.001;
    }

    overallgain = gaincontrol*softstart;

    //What to do if the lever is pulled back or pushed forwards or not doing anything:
    Balance_point = 514;

    if (adc3 > 100)
        Balance_point = 534;

    if (adc5>100)
        Balance_point = 494;

    PORTB |= (1<<PB2); //Port B2 turned on/off once per loop so I can measure
                       //loop time with an oscilloscope

    /*ACCELEROMETER signal processing*/

    /*Subtract offsets*/

    x_acc = (float) accsum - Balance_point; //accsum is SG value for accelerometer, not
                                            //a true "sum" so no need to divide by 7

    if (x_acc < -250)
        x_acc = -250; //Cap acceleration values to a range of -250 to +250 (80
                      //degree tilt each way).
    if (x_acc > 250)
        x_acc = 250;

    /* Accelerometer angle change is about 3.45 units per degree tilt in
       range 0-30 degrees(sin theta). Convert tilt to degrees of tilt from
       accelerometer sensor. Sin angle roughly = angle for small angles so
       no need to do trigonometry. x_acc below is now in DEGREES */

    x_accdeg= (float) x_acc/-3.45; //The minus sign corrects for a back
                                   //to front accelerometer mounting!

    /* GYRO signal processing*/

    /* Subtract offsets: Sensor reading is 0-1024 so "balance point" i.e. my required
       zero point will be that reading minus 512. */

    /* Gyro angle change of 20mV per deg per sec from datasheet gives change
       of 4.096 units (on the scale of 0 - 1023) per degree per sec angle change.
       This limits the rate of change of gyro angle to just less than the
       maximum rate it is actually capable of measuring (100 deg/sec). Note
       all these fractions are rounded up to an integer later just before
       it is sent to the PWM generator which in turn is connected to the
       motor controller. */

    gangleratedeg = (float)((gyrosum/7) - 508)/4.096; //gyrosum is a sum of a group
                                                      //of 7 samples so divide by 7 for gyro value
    if (gangleratedeg < -92)
        gangleratedeg = -92;
    if (gangleratedeg > 92)
        gangleratedeg = 92;

    /* I turn port B2 on and off once per main program cycle so I can attach an
       oscilloscope to it and work out the program cycle time.
       I use the cycle time to work out gyro angle change per cycle where you
       have to know the length of this time interval. */
    PORTB &= (0<<PB2);

    /* ti represents scaling for the "i" or integral factor (currently 2.2 here)
       gyroangledt is anglechange since last CYCLE in degrees from gyro sensor,
       where ti is scaling factor (should in theory be about 1 but 2.2 makes
       board feel tighter)

       ganglerate is now in units of degrees per second.
       aa varies the time constant, that is, a smaller aa value makes
       accelerometer time constant longer as it slowly corrects for
       the gyro drift. */

    aa=0.005;

    gyroangledt = (float)ti*cycle_time*gangleratedeg;
    gangleraterads = (float)gangleratedeg*0.017453;

    /* New angle in DEGREES is old angle plus change in angle from gyro
       since last cycle with little bit of new accel reading factored in. */
    angle = (float)((1-aa) * (angle+gyroangledt)) + (aa * x_accdeg); //The main angle calculating function*/

    //Convert angle from degrees to radians

    anglerads=(float)angle*0.017453;

    balance_torque=(float)(4.5*anglerads) + (0.5*gangleraterads);

    cur_speed = (float)(cur_speed + (Throttle_pedal * balance_torque * cycle_time)) * 0.999;

    /* The level value is from -1 to +1 and represents the duty cycle to be sent to
       the motor. Converting to radians helps us stay within these limits. */

    level = (balance_torque + cur_speed) * overallgain;
}

/* Configure timer and set up the output pins OC1A(Pin PD5 on my micro) and
   OC1B (Pin PD4 on my micro) as phase-correct PWM channels.

   Note: Some strongly feel that locked-antiphase is the way to go as get
   regenerative braking and good control around mid-balance point. The downside
   is that you can get a lot more noise and voltage spikes in system but
   these can be smoothed out with filters.

   Others are far more expert on this than I am so need to look into this
   for yourself but this is my understanding.

   My aim is to start with phase-correct as I just about understand it and
   others have used it OK, then develop from there. */
void timer_init()
{
    TCCR0 = 0 |
    (1<<CS02) | (1<<CS01) | (1<<CS00); // External clock to Pin T0 Clock on rising edge/1024

    // PWM mode is "PWM, Phase Correct, 10-bit"
    TCCR1A = 0 |
        (1<<COM1A1) | (1<<COM1A0) | // set on match up, clear on match down
        (1<<COM1B1) | (1<<COM1B0) | // set on match up, clear on match down

        (1<<WGM11) | (1<<WGM10); //OCR1_Max is 1023 so these are set like this

    TCCR1B = 0 |
        (1<<CS10); // Prescaler divide by 1 see P131 datasheet about prescaling
                      values to change here.
    /* 16 MHz / 1 / 1024 / 2 gives 8 kHz, probably about right. */
}

void set_motor()
/* The leveli terms is the level term rescaled from -1023 to +1023 as an
   integer ready to send to the PWM motor control ports that are in
   turn connected to the OSMC. */
{
    //if (level<-0.9) level= -0.9; //Checks we are within sensible limits
    //if (level>0.9) level=0.9;

    int16_t leveli = (int16_t)(level*1023); //NOTE: here we take the floating
                                            //point value we have ended up with
                                            //for "level", we multiply it by 1023
                                            //and then make it into an integer
                                            //before feeding the value into
                                            //the PWM generator as "leveli"

    if (leveli<-1020)
        leveli=-1020; //Double-checks that we are within sensible PWM limits as do
                      //not want to suddenly be thrown off the board
    if (leveli>1020)
        leveli=1020;

    /* Set up LED or buzzer on Port B1 to warn me to slow down if torque to be
       delivered is more than 50% of max possible. The reason for this is that
       you always need some reserve motor power in case you start tipping
       forward at speed. If the motor is already running flat-out you would
       be about to fall over at high speed! Some use an auto-tip back routine
       to automatically limit top speed. For now I will do it this way as easier. */

    if (level<-0.7 || level>0.7) {
        PORTB |= (1<<PB1);
    }
    else {
        PORTB &= (0<<PB1);
    }

    softstart = (float) softstart+0.001;
    if (softstart>1.0)
        softstart=1.0;

    //PORTC |= (0<<PC1);  // AHI=1  PinC3, BHI=1 PinC2 set both to ON for OSMC to
                          //work and both to OFF to shut motor down.

    /*NOTE: I am not sure why, but to stop the motor cutting out on direction
            changes I had in the end to hard wire AHI and BHI to +12 V. */

    /* Un-disabled OSMC by setting PinC1 output to zero, a 1 would disable the OSMC. */
    PORTC |= 0x0c; //Make C1 pulled down so un-disables the OSMC i.e. enables it.
    PORTC &= ~0x02; //Disable is off
    if (leveli<0) {
        OCR1A = -leveli; // ALI is PWM. Going backwards as leveli variable is a
                         //negative signed value, keep the minus sign in here!
        OCR1B = 0;       // BLI = 0
    }
    else {
        OCR1A = 0;       // ALI = 0      going forwards as leveli variable is a positive signed value
        OCR1B = leveli;  // BLI is PWM
    }
}

void loop()
{
    InitPorts();
    adc_init();
    timer_init();

    /*  Initial tilt-start code
        Turn on micro while board tipped to one side, rider about to step
        onto it, if tilt angle crosses zero (mid) point balance algorithm
        becomes operational otherwise locked in this loop forever until
        it is tipped to level position as rider gets onto the board. */
    tipstart=0;
    accelraw = 0;

    while (tipstart<1){
        // You need this to allow the SG filter to wind up to the proper
        //stable value when you first turn machine on, before looking
        //at the value of accsum (below).

        for (i=0; i<20; i++) {
            sample_inputs();
        }

        if (accsum<504 || accsum>524) {
            //   if (x_accdeg>0) {
            tipstart=0;
        }
        else {
            tipstart=1;
            softstart=0.4;
        }
    }

    angle=0;
    cur_speed=0;
    /* End of tilt start code. If go beyond this point then machine
       has become level and is active. */

    sei();

    while (1) {
        sample_inputs();
        set_motor();
    }
}

顺便说一句,我正在使用 Arduino 编译器(您可以在 下载 Arduino 软件)。

I'm trying to modify this code in an attempt to make it work on an Arduino Mega. I'm pretty much new to C so, I may have made some major mistakes. By the way, this is for a self balancing skateboard.

This code is taken from an ATmega32 (from here and I'm trying to make it work on a Arduino Mega).

This code was writen for an ATmega32 development board.

But I encounter this error:

o: In function main':</br>
C:\Users\*******\AppData\Local\Temp\build27006.tmp/Test2.cpp:406:</br>
undefined reference to
setup'

How come? I don't even have a reference to setup in here!

Here is my code:

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <math.h>

#define CLOCK_SPEED  16000000
#define OCR1_MAX   1023

typedef unsigned char u8;
void set_motor_idle(void);
void InitPorts(void);
float level = 0;
float Throttle_pedal;
float aa;
float accelraw;
float x_acc;
float accsum;
float x_accdeg;

float gyrosum;

float gangleratedeg;
float gangleraterads;
float ti = 2.2;

float overallgain;
float gaincontrol;
float batteryvolts = 24;
float gyroangledt;
float angle;
float anglerads;
float balance_torque;
float softstart;

float cur_speed;
float cycle_time = 0.0064;
float Balance_point;
float a0, a1, a2, a3, a4, a5, a6; //Savitzky-Golay variables for accelerometer.

float TCCR0;

int i;
int j;
int tipstart;

void InitPorts(void)
{
    PORTC = 0x00;  //Port C pullups set to low (no output voltage) to begin with.
    DDRC = 0xFF; //Port C pins all set as output via the port C direction register.
    //PORTC |= (1<<PC1); //Make C1 +ve so disables OSMC during startup.

    DDRA = 0x00; //All port A pins set as input.
    PORTA = 0x00; //Port A input pullups set to low pullups.

    DDRD = 0xFF; //Configure all port D pins as output as prerequisite
               //for OCR1A (PinD5) and OCR1B (Pin D4) working properly.

    PORTB = 0x00;  //Port B pullups set to low (no output voltage) to begin with.
    DDRB = 0xFF; //All port B pins set to output.
}

/*
  IO:

  I am using a ATMega32 16 MHz with an external crystal clock. New planned pin
  arrangement to OSMC motor controller.

    PC4        Onboard LED
    PD5/OC1A   ALI -> OSMC pin 6
    PD4/OC1B   BLI -> OSMC pin 8
    PC1        Disable -> OSMC pin 4
    PC2        BHI -> OSMC pin 7
    PC3        AHI -> OSMC pin 5
    PA6/ADC6   Vbatt/10 -> OSMC pin 3
    PA1/ADC1   pitch rate gyro
    PA0/ADC0   accelerometer
*/

void adc_init(void) {
    /* Turn off analogue comparator as we don't use it */
    ACSR = (1 << ACD);

    /* Select PA0 */
    ADMUX = 0;
    ADMUX |=(1<<REFS0); //This tells it to use VCC (approx. 5 V) as the reference
                        //voltage NOT the default which is the internal 2.5V reference
    /* Set ADC prescaler to 128, enable ADC, and start conversion. */
    ADCSRA = 0 | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
               | (1<<ADEN)  //Enable ADC
               | (1<<ADSC); //Start first conversion
    /* Wait until bogus first conversion is finished */
    while (ADCSRA & (1 << ADSC)) {
    }
}


uint16_t adc_read(uint8_t channel) {
    /* Select channel */
    ADMUX = channel;
    ADMUX |= (1<<REFS0); //Here it is again
    /* Start conversion */
    ADCSRA |= (1 << ADSC);
    /* Wait until conversion finished */
    while (ADCSRA & (1 << ADSC)) {
    }
    /* Return the result */
    return ADCW;
}

/* 156 cycles per sec, 6.4 ms per cycle MEASURED ON OSCILLOSCOPE. */
/* Read all the ADC inputs and do some conversion. */
void sample_inputs(void) {
    uint16_t adc0, adc1, adc2, adc3, adc4, adc5;

    gyrosum = 0;
    adc0 = adc_read(0); /* Accelerometer pin PA0 */
    accelraw = (float) adc0;

    for (j=0; j<7; j++) {
        adc1 = adc_read(1); //Gyro pin PA1
        gyrosum = (float) gyrosum + adc1; //Using a mean of 7 samples per loop for the gyro so
                                          //it gets a complete update with each loop of the program.
    }

    adc2 = adc_read(2); /* Grey wire overallgain (via cutout switch), position PA2. */
    adc3 = adc_read(3); /* Position lever pulled back position PA3. */
    adc4 = adc_read(4); /* Throttle_pedal, position PA4. */
    adc5 = adc_read(5); /* Position lever pushed forwards, position PA5. */
    //adc6 = adc_read(6); /* Vbatt input from OSMC (not used at present), position PA6. */

    //Sav Golay filter for accelerometer only.
    a0 = a1;
    a1 = a2;
    a2 = a3;
    a3 = a4;
    a4 = a5;
    a5 = a6;
    a6 = (float) accelraw;
    accsum = (float) ((-2*a0) + (3*a1) + (6*a2) + (7*a3) +
                      (6*a4) + (3*a5) + (-2*a6))/21;  //Sav Golay calculation

    gaincontrol = (float) gaincontrol*0.9 + 0.1*adc2/341; //Smooths any voltage spikes and gives range 0-3.

    Throttle_pedal=(float) Throttle_pedal*0.9 + 0.1*adc4/341; //Smooths any voltage spikes and gives range 0-3

    //Cuts the motor if the dead mans button is let go
    //(gaincontrol variable also wired in through this button to adc2
    if (adc2<100) {
        Throttle_pedal = 0.001;
        gaincontrol = 0.001;
    }

    overallgain = gaincontrol*softstart;

    //What to do if the lever is pulled back or pushed forwards or not doing anything:
    Balance_point = 514;

    if (adc3 > 100)
        Balance_point = 534;

    if (adc5>100)
        Balance_point = 494;

    PORTB |= (1<<PB2); //Port B2 turned on/off once per loop so I can measure
                       //loop time with an oscilloscope

    /*ACCELEROMETER signal processing*/

    /*Subtract offsets*/

    x_acc = (float) accsum - Balance_point; //accsum is SG value for accelerometer, not
                                            //a true "sum" so no need to divide by 7

    if (x_acc < -250)
        x_acc = -250; //Cap acceleration values to a range of -250 to +250 (80
                      //degree tilt each way).
    if (x_acc > 250)
        x_acc = 250;

    /* Accelerometer angle change is about 3.45 units per degree tilt in
       range 0-30 degrees(sin theta). Convert tilt to degrees of tilt from
       accelerometer sensor. Sin angle roughly = angle for small angles so
       no need to do trigonometry. x_acc below is now in DEGREES */

    x_accdeg= (float) x_acc/-3.45; //The minus sign corrects for a back
                                   //to front accelerometer mounting!

    /* GYRO signal processing*/

    /* Subtract offsets: Sensor reading is 0-1024 so "balance point" i.e. my required
       zero point will be that reading minus 512. */

    /* Gyro angle change of 20mV per deg per sec from datasheet gives change
       of 4.096 units (on the scale of 0 - 1023) per degree per sec angle change.
       This limits the rate of change of gyro angle to just less than the
       maximum rate it is actually capable of measuring (100 deg/sec). Note
       all these fractions are rounded up to an integer later just before
       it is sent to the PWM generator which in turn is connected to the
       motor controller. */

    gangleratedeg = (float)((gyrosum/7) - 508)/4.096; //gyrosum is a sum of a group
                                                      //of 7 samples so divide by 7 for gyro value
    if (gangleratedeg < -92)
        gangleratedeg = -92;
    if (gangleratedeg > 92)
        gangleratedeg = 92;

    /* I turn port B2 on and off once per main program cycle so I can attach an
       oscilloscope to it and work out the program cycle time.
       I use the cycle time to work out gyro angle change per cycle where you
       have to know the length of this time interval. */
    PORTB &= (0<<PB2);

    /* ti represents scaling for the "i" or integral factor (currently 2.2 here)
       gyroangledt is anglechange since last CYCLE in degrees from gyro sensor,
       where ti is scaling factor (should in theory be about 1 but 2.2 makes
       board feel tighter)

       ganglerate is now in units of degrees per second.
       aa varies the time constant, that is, a smaller aa value makes
       accelerometer time constant longer as it slowly corrects for
       the gyro drift. */

    aa=0.005;

    gyroangledt = (float)ti*cycle_time*gangleratedeg;
    gangleraterads = (float)gangleratedeg*0.017453;

    /* New angle in DEGREES is old angle plus change in angle from gyro
       since last cycle with little bit of new accel reading factored in. */
    angle = (float)((1-aa) * (angle+gyroangledt)) + (aa * x_accdeg); //The main angle calculating function*/

    //Convert angle from degrees to radians

    anglerads=(float)angle*0.017453;

    balance_torque=(float)(4.5*anglerads) + (0.5*gangleraterads);

    cur_speed = (float)(cur_speed + (Throttle_pedal * balance_torque * cycle_time)) * 0.999;

    /* The level value is from -1 to +1 and represents the duty cycle to be sent to
       the motor. Converting to radians helps us stay within these limits. */

    level = (balance_torque + cur_speed) * overallgain;
}

/* Configure timer and set up the output pins OC1A(Pin PD5 on my micro) and
   OC1B (Pin PD4 on my micro) as phase-correct PWM channels.

   Note: Some strongly feel that locked-antiphase is the way to go as get
   regenerative braking and good control around mid-balance point. The downside
   is that you can get a lot more noise and voltage spikes in system but
   these can be smoothed out with filters.

   Others are far more expert on this than I am so need to look into this
   for yourself but this is my understanding.

   My aim is to start with phase-correct as I just about understand it and
   others have used it OK, then develop from there. */
void timer_init()
{
    TCCR0 = 0 |
    (1<<CS02) | (1<<CS01) | (1<<CS00); // External clock to Pin T0 Clock on rising edge/1024

    // PWM mode is "PWM, Phase Correct, 10-bit"
    TCCR1A = 0 |
        (1<<COM1A1) | (1<<COM1A0) | // set on match up, clear on match down
        (1<<COM1B1) | (1<<COM1B0) | // set on match up, clear on match down

        (1<<WGM11) | (1<<WGM10); //OCR1_Max is 1023 so these are set like this

    TCCR1B = 0 |
        (1<<CS10); // Prescaler divide by 1 see P131 datasheet about prescaling
                      values to change here.
    /* 16 MHz / 1 / 1024 / 2 gives 8 kHz, probably about right. */
}

void set_motor()
/* The leveli terms is the level term rescaled from -1023 to +1023 as an
   integer ready to send to the PWM motor control ports that are in
   turn connected to the OSMC. */
{
    //if (level<-0.9) level= -0.9; //Checks we are within sensible limits
    //if (level>0.9) level=0.9;

    int16_t leveli = (int16_t)(level*1023); //NOTE: here we take the floating
                                            //point value we have ended up with
                                            //for "level", we multiply it by 1023
                                            //and then make it into an integer
                                            //before feeding the value into
                                            //the PWM generator as "leveli"

    if (leveli<-1020)
        leveli=-1020; //Double-checks that we are within sensible PWM limits as do
                      //not want to suddenly be thrown off the board
    if (leveli>1020)
        leveli=1020;

    /* Set up LED or buzzer on Port B1 to warn me to slow down if torque to be
       delivered is more than 50% of max possible. The reason for this is that
       you always need some reserve motor power in case you start tipping
       forward at speed. If the motor is already running flat-out you would
       be about to fall over at high speed! Some use an auto-tip back routine
       to automatically limit top speed. For now I will do it this way as easier. */

    if (level<-0.7 || level>0.7) {
        PORTB |= (1<<PB1);
    }
    else {
        PORTB &= (0<<PB1);
    }

    softstart = (float) softstart+0.001;
    if (softstart>1.0)
        softstart=1.0;

    //PORTC |= (0<<PC1);  // AHI=1  PinC3, BHI=1 PinC2 set both to ON for OSMC to
                          //work and both to OFF to shut motor down.

    /*NOTE: I am not sure why, but to stop the motor cutting out on direction
            changes I had in the end to hard wire AHI and BHI to +12 V. */

    /* Un-disabled OSMC by setting PinC1 output to zero, a 1 would disable the OSMC. */
    PORTC |= 0x0c; //Make C1 pulled down so un-disables the OSMC i.e. enables it.
    PORTC &= ~0x02; //Disable is off
    if (leveli<0) {
        OCR1A = -leveli; // ALI is PWM. Going backwards as leveli variable is a
                         //negative signed value, keep the minus sign in here!
        OCR1B = 0;       // BLI = 0
    }
    else {
        OCR1A = 0;       // ALI = 0      going forwards as leveli variable is a positive signed value
        OCR1B = leveli;  // BLI is PWM
    }
}

void loop()
{
    InitPorts();
    adc_init();
    timer_init();

    /*  Initial tilt-start code
        Turn on micro while board tipped to one side, rider about to step
        onto it, if tilt angle crosses zero (mid) point balance algorithm
        becomes operational otherwise locked in this loop forever until
        it is tipped to level position as rider gets onto the board. */
    tipstart=0;
    accelraw = 0;

    while (tipstart<1){
        // You need this to allow the SG filter to wind up to the proper
        //stable value when you first turn machine on, before looking
        //at the value of accsum (below).

        for (i=0; i<20; i++) {
            sample_inputs();
        }

        if (accsum<504 || accsum>524) {
            //   if (x_accdeg>0) {
            tipstart=0;
        }
        else {
            tipstart=1;
            softstart=0.4;
        }
    }

    angle=0;
    cur_speed=0;
    /* End of tilt start code. If go beyond this point then machine
       has become level and is active. */

    sei();

    while (1) {
        sample_inputs();
        set_motor();
    }
}

BTW, I'm using the Arduino compiler (you can find it at Download the Arduino Software).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

终陌 2024-08-23 21:58:12

怎么会呢?我什至没有在这里设置的参考!

这是因为您没有对 setup 的引用,所以它会抱怨。

Arduino 代码生成一个 main (用于此处的讨论)基本上如下所示:

int main(int argc, char **argv) {
    setup();
    while(1) {
        loop();
    }
}

因此,您应该将 loop 函数重命名为 setup 并采取这部分:

while (1) {
  sample_inputs();
  set_motor();
}

删除 while 循环,并将这两个函数调用放入一个名为 loop 的新函数中。

How come? I dont even have a reference to setup in here!

It's because you don't have a reference to setup that it's complaining.

Arduino code generates a main that (for the discussion here) basically looks like this:

int main(int argc, char **argv) {
    setup();
    while(1) {
        loop();
    }
}

So, you should rename your loop function to setup and take this part:

while (1) {
  sample_inputs();
  set_motor();
}

drop the while loop, and put those two function calls into a new function called loop.

揽清风入怀 2024-08-23 21:58:12

Arduino 语言要求您定义两个函数:setup() 和loop()。

如果你没有任何东西需要 setup(),你应该定义一个空函数来满足语言要求:

void setup()
{
    // do nothing
}

The Arduino language requires you to define two functions, setup() and loop().

If you don't have anything to setup(), you should define an empty function to satisfy the language requirements:

void setup()
{
    // do nothing
}
深府石板幽径 2024-08-23 21:58:12

包含的代码甚至没有 main 函数。在我看来,这就像你的工具链中的设置问题,或者你一直在调查错误的 cpp 文件。

找到 Test2.cpp 和第 406 行(在名为 main 的函数中)

The included code doesn't even have a main function. It looks to me like a setup issue in your toolchain, or else you've been investigating the wrong cpp file.

Find Test2.cpp and line 406 (in a function called main)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文