Бесполезные ошибки при написании кода Arduino C++ в Tinkercad

Извините, если некоторые из моих источников выглядят действительно плохо. Это моя первая попытка написать код как на Arduino, так и на C++. Я обычно остаюсь в своей комфортной зоне с #.

Я получаю следующие ошибки при попытке запустить свой источник в цепи Tinkercad. То, как Tinkercad выдает ошибки, ужасно для изучения. Любой, кто сможет указать на мои ошибки, с которыми он согласен, будет очень полезен.

Ошибки

 - 2:23: error: use of enum 'LedActionTypes' without previous
   declaration
 - 4:23: error: use of enum 'SignalTypes' without previous declaration
 - 4:64: error: use of enum 'SignalDirections' without previous declaration
 - 5:23: error: use of enum 'SignalTypes' without previous declaration
 - 5:64: error: use of enum 'SignalDirections' without previous declaration
 - 5:103: error: use of enum 'DigitalSignalValues' without previous declaration
 - 8:16: error: variable or field 'AddAction' declared void
 - 8:16: error: 'LedAction' was not declared in this scope

Мой исходный код

/* Enums */
enum SignalTypes
{
    General = 0,
    Analog = 1,
    Digital = 2,
};

enum SignalDirections
{
    Inbound = 0x0,
    Outbound = 0x1,
};

enum DigitalSignalValues
{
    Low = 0x0,
    High = 0x1,
};

enum LedActionTypes
{
    None = 0,
    ChangeBrightness = 1,
};

/* LED Action object */
class LedAction {
    // Functions
    void Constructor(enum LedActionTypes action, int intensity, int delay)
    {
        // Check for valid intensity value
        if (intensity < 0)
            intensity = 0;
        if (intensity > 255)
            intensity = 255;
        Intensity = intensity;

        Finished = false;
        Action = action;

        CompleteOn = millis() + delay;
    }

public:
    // Properties
    boolean Finished;
    enum LedActionTypes Action = None;
    int Intensity = 0;
    unsigned long CompleteOn = 0;


    // Constructor
    LedAction()
    {
        Constructor(Action, Intensity, 0);
    }
    LedAction(enum LedActionTypes action)
    {
        Constructor(action, Intensity, 0);
    }
    LedAction(enum LedActionTypes action, int intensity, int delay)
    {
        Constructor(action, intensity, delay);
    }


    // Methods
    void Loop() {
        if (Finished) { return; }

        unsigned long currentTimeStamp = millis();

        if (CompleteOn >= currentTimeStamp)
        {
            //Process the action
            Finished = true;
        }
    }
};


/* LED object */
class Led {
    // Functions
    void Constructor(enum SignalTypes signalType, byte pbPin, enum SignalDirections signalDirection, int intensity)
    {
        // Check for valid intensity value
        if (intensity < 0)
            intensity = 0;
        if (intensity > 255)
            intensity = 255;
        Intensity = intensity;

        Constructor(SignalType, PBPin, SignalDirection, DigitalSignalValue);
    }
    void Constructor(enum SignalTypes signalType, byte pbPin, enum SignalDirections signalDirection, enum DigitalSignalValues signalValue)
    {
        SignalType = signalType;
        PBPin = pbPin;
        SignalDirection = signalDirection;
        DigitalSignalValue = signalValue;
    }

public:
    // Properties
    byte PBPin;
    int Intensity;
    enum DigitalSignalValues DigitalSignalValue;
    enum SignalTypes SignalType = Analog;
    enum SignalDirections SignalDirection = Outbound;
    LedAction Actions[20]{ LedAction(None) };


    // Constructor
    Led()
    {
        Constructor(SignalType, 0, SignalDirection, 0);
    }
    Led(byte pbPin, enum SignalDirections signalDirection, int intensity)
    {
        Constructor(SignalType, pbPin, signalDirection, intensity);
    }
    Led(byte pbPin, enum SignalDirections signalDirection, enum DigitalSignalValues signalValue)
    {
        Constructor(SignalType, pbPin, signalDirection, signalValue);
    }
    Led(enum SignalTypes signalType, byte pbPin, enum SignalDirections signalDirection, int intensity)
    {
        Constructor(signalType, pbPin, signalDirection, intensity);
    }
    Led(enum SignalTypes signalType, byte pbPin, enum SignalDirections signalDirection, enum DigitalSignalValues signalValue)
    {
        Constructor(signalType, pbPin, signalDirection, signalValue);
    }


    // Methods
    void Setup()
    {
        switch (SignalType)
        {
        case Analog:
            analogWrite(PBPin, Intensity);
            break;
        case Digital:
            digitalWrite(PBPin, Intensity);
            pinMode(PBPin, SignalDirection);
            break;
        }
    }

    void Loop()
    {
        int n;

        // Loop through all actions and find unfinished ones then fire them off
        for ( n=0 ; n<20 ; ++n )
        {
            if (!Actions[n].Finished)
            {
                Actions[n].Loop();
                if (Actions[n].Finished)
                {
                    //Action was just flagged ready to process
                    switch (Actions[n].Action)
                    {
                    case ChangeBrightness:
                        digitalWrite(PBPin, Actions[n].Intensity);
                        break;
                    }

                }
            }
        }
    }

    void AddAction(LedAction action)
    {
        int n;

        // Loop through all actions and find an unfinished one then reuse it
        for (n = 0; n < 20; ++n)
        {
            if (!Actions[n].Finished)
            {
                action.Finished = false;
                Actions[n] = action;
                break;
            }
        }
    }

    void ClearAllActions()
    {
        int n;

        // Loop through all actions and mark all as finished
        for (n = 0; n < 20; ++n)
        {
            if (!Actions[n].Finished)
            {
                Actions[n].Finished = true;
            }
        }
    }
};

Пример кода на Tinkercad Circuits можно найти по адресу...https://www.tinkercad.com/things/gmGeFVKOA3e-adrunio-test/editel

Оказавшись на странице, нажмите кнопку воспроизведения "Моделировать" (слева внизу), а затем нажмите кнопку "Начать моделирование" вверху. Вы должны увидеть те же ошибки, что и я.

1 ответ

Решение

Хорошо, думаю, я нашел свой ответ...

После нескольких разговоров с Tinkercad и отличной командой поддержки мне сказали, что они используют старую версию Arduino для компиляции своего кода. Что ж, весь код, который я пишу, и IDE, в которой я пишу, основаны на последних выпусках всего. Думаю, именно здесь и возникает моя проблема.

В настоящее время при попытке скомпилировать следующий код в текущей версии, которую использует Tinkercad, я получаю соответствующую ошибку, которая следует...

enum TestEnum
{
    OptOne = 1,
    OptTwo = 2
};

class TestClass {
private:
    void InitilizeClass(enum TestEnum te)
    { }

public:
    TestClass(enum TestEnum te)
    { }
};

void setup()
{ }

void loop()
{ }

Как видите, я пытаюсь создать в своем классе функцию под названием InitializeClass()который принимает мое перечисление в качестве параметра. Компилятору не нравится этот бит, а выделение ошибки вместе с возвращаемой ошибкой ужасно по какой-то причине мне ничего не говорит!

Однако, если я изменю класс, чтобы использовать только перечисление в самом конструкторе, он, похоже, компилируется нормально без ошибок.

enum TestEnum
{
    OptOne = 1,
    OptTwo = 2
};

class TestClass {
private:
    void InitilizeClass()
    { }

public:
    TestClass(enum TestEnum te)
    { }
};

void setup()
{ }

void loop()
{ }

Эта проблема

Я хотел создать класс, который имеет как можно меньше повторяющегося кода, обычно я стараюсь кодировать именно так. Если мне придется ввести один и тот же код дважды... Начните с того, чтобы превратить его в функцию. Таким образом, а) меньше кода и б) если вам когда-либо понадобится изменить логику, вы меняете ее в одном месте, а не в нескольких местах. Поэтому я обычно начинаю с того, чтобы мои классы выглядели так...

enum TestEnum
{
    OptOne = 1,
    OptTwo = 2
};

class TestClass {
private:
    void InitilizeClass(enum TestEnum te, int n, int t)
    {
        if (n < 0)
            n = 0;
        if (n > 255)
            n = 255;
        TE = te;
        N = n;
        T = t;
    }

public:
    enum TestEnum TE = OptOne;
    int N = 0;
    int T = 0;

    TestClass(enum TestEnum te)
    { InitilizeClass(te, 0, 0); }
    TestClass(enum TestEnum te, int n)
    { InitilizeClass(te, n, 0); }
    TestClass(enum TestEnum te, int n, int t)
    { InitilizeClass(te, n, t); }
};

void setup()
{ }

void loop()
{ }

Это отлично работает в VS IDE (C++), а также в последней версии Arduino IDE. Однако, поскольку Tinkercad использует старый компилятор Arduino, он мне подходит, используя перечисления в функции частного класса. (Обновление: только что выяснилось, что это происходит в ЛЮБОЙ функции класса! Не только в частной.)

Решение

Так что все это время я думал с менталитетом С # при кодировании моего проекта Arduino, когда мне следовало думать больше, как на С ++. Что ж, в свою защиту я, в конце концов, насквозь парень с C#. Я люблю его НАСТОЛЬКО больше, чем C++. Ну почти во всех смыслах. Видимо, есть исключения. Недавно я узнал, что, хотя C# не позволяет этого, С ++ ДЕЙСТВИТЕЛЬНО позволяет перегружать конструкторы классов! Это меняет все, как я пишу свои классы на C++. Теперь у функции частного класса нет причин для инициализации класса. Так что у меня может быть что-то вроде следующего...

enum TestEnum
{
    OptOne = 1,
    OptTwo = 2
};

class TestClass {
public:
    enum TestEnum TE = OptOne;
    int N = 0;
    int T = 0;

    TestClass(enum TestEnum te)
    { TestClass(te, 0, 0); }
    TestClass(enum TestEnum te, int n)
    { TestClass(te, n, 0); }
    TestClass(enum TestEnum te, int n, int t)
    { TestClass(te, n, t); }
};

void setup()
{ }

void loop()
{ }

Что мои друзья прекрасно компилируются в старых компиляторах Arduino. Это также экономит место для другого кода (эти чипы ATTiny не огромны, поэтому программа меньшего размера всегда выигрывает!).

Другие вопросы по тегам