element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Connected Cloud Challenge
  • Challenges & Projects
  • Design Challenges
  • Connected Cloud Challenge
  • More
  • Cancel
Connected Cloud Challenge
Blog Learning Mbed (Blog #6)
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Events
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: neuromodulator
  • Date Created: 20 May 2020 7:11 AM Date Created
  • Views 1856 views
  • Likes 7 likes
  • Comments 8 comments
Related
Recommended

Learning Mbed (Blog #6)

neuromodulator
neuromodulator
20 May 2020

Learning Mbed

 

To get started with Mbed I began programming a non-trivial but not complex LED library. The Pioneer PSOC6 board contains 3 user programmable LEDs: an RGB LED, an orange LED and a red LED.

 

image

 

The source code runs 2 threads: main() and ledThread(). main() controls the LEDs by sending messages, through an Mbeds' Queue object, to ledThread(). LEDs can operate in 3 different modes: on or off, oscillating and pulsing. The program is made of 3 files:

 

 

main.cpp

#include "mbed.h"

 

#include "LedThread.h"

 

 

static Thread ledThreadObject;

 

 

int main()

{

    ledThreadObject.start(ledThread);

 

    while (true)

    {

        printf("    O: Pulse 0.2 s \n");

        ThisThread::sleep_for(5'000);

        pulse(Led::o, 0.2);

 

        printf("    R: Pulse 1.0 s \n");

        ThisThread::sleep_for(5'000);

        pulse(Led::r, 1.0);

 

        printf("RGB_R: On\n");

        ThisThread::sleep_for(5'000);

        set(Led::rgbR, true);

 

        printf("RGB_R: Off\n");

        ThisThread::sleep_for(5'000);

        set(Led::rgbR, false);

 

        printf("RGB_G: frequency: 5.0 Hz\n");

        ThisThread::sleep_for(5'000);

        oscillate(Led::rgbG, 1.f / 5.f);

 

        printf("RGB_G: frequency: 15.0 Hz\n");

        ThisThread::sleep_for(5'000);

        oscillate(Led::rgbG, 1.f / 15.f);

 

        printf("RGB_G: Off\n");

        ThisThread::sleep_for(5'000);

        set(Led::rgbG, false);

 

        printf("RGB_B: frequency: 2.0 Hz\n");

        ThisThread::sleep_for(5'000);

        oscillate(Led::rgbB, 1.f / 2.f);

 

        printf("RGB_B: pulse: 2.0 s\n");

        ThisThread::sleep_for(5'000);

        pulse(Led::rgbB, 2.0);

    }

}

 

 

LedThread.h

#ifndef LED_THREAD_H

    #define LED_THREAD_H

 

 

    // LED types

    enum class Led

    {

        r,

        o,

        rgbR,

        rgbG,

        rgbB,

    };

 

 

    // LED thread

    void ledThread();

  

    // Set LED at specified state

    void set(Led led, bool state);

 

    // Generate a LED pulse at specified duration

    void pulse(Led led, float duration);

 

    // Oscillate LED at specified period (50% duty cycle)

    void oscillate(Led led, float period);

 

 

#endif

 

 

LedThread.cpp

#include <cmath>

 

#include "mbed.h"

#include "LedThread.h"

 

 

enum class Mode

{

    continuous,

    pulsed,

    oscillation

};

 

struct Properties

{

    Mode  mode_    = Mode::continuous;

    float period_  = 0.;

    float elapsed_ = 0.;

};

 

struct Message

{

    Led   led_;

    Mode  mode_;

    float value_;    // this can be on/off state (mode_ = Mode::continuous), pulse duration (mode_ = Mode::Pulsed), or period (mode_ = Mode::oscillation)

};

 

 

static Queue<Message, 16>     queue;

static MemoryPool<Message, 16> pool;

 

static uint64_t t0 = 0;

static uint64_t t1 = 0;

 

static DigitalOut ledO(LED1);        // Red LED

static DigitalOut ledR(LED2);        // Orange LED

static DigitalOut ledRgbR(LED3);     // RGB LED red

static DigitalOut ledRgbG(LED4);     // RGB LED green

static DigitalOut ledRgbB(LED5);     // RGB LED blue

 

static DigitalOut* digitalOut[5];

static Properties  properties[5];

 

 

void ledThread()

{

    digitalOut[static_cast<int>(Led::o)]    = &ledO;

    digitalOut[static_cast<int>(Led::r)]    = &ledR;

    digitalOut[static_cast<int>(Led::rgbR)] = &ledRgbR;

    digitalOut[static_cast<int>(Led::rgbG)] = &ledRgbG;

    digitalOut[static_cast<int>(Led::rgbB)] = &ledRgbB;

   

    for (int led = 0; led < 5; led++)

        *digitalOut[led] = 1;

 

    while (true)

    {

        t0 = get_ms_count();

        float delta = static_cast<float>(t0 - t1) / 1000.f;

        t1 = t0;

 

        for (int led = 0; led < 5; led++)

        {

            switch (properties[led].mode_)

            {

            case Mode::pulsed:

                properties[led].elapsed_ += delta;

 

                if (properties[led].elapsed_ >= properties[led].period_)

                {

                    properties[led].mode_ = Mode::continuous;

                    *digitalOut[led] = 1;

                }

                break;

 

            case Mode::oscillation:

                properties[led].elapsed_ += delta;

                               

                if (properties[led].elapsed_ >= .5f * properties[led].period_)

                {

                    properties[led].elapsed_ -= .5f * properties[led].period_;

                    *digitalOut[led] = !*digitalOut[led];

                }

                break;

           

            default:

                break;

            }

        }

 

        osEvent event = queue.get(0);

       

        if (event.status == osEventMessage)

        {

            Message* message = static_cast<Message*>(event.value.p);

           

            int led = static_cast<int>(message->led_);

           

            properties[led].mode_    = message->mode_;

            properties[led].period_  = message->value_;

            properties[led].elapsed_ = 0.f;

           

            if (message->mode_ == Mode::continuous && !message->value_)

                *digitalOut[led] = 1;

            else

                *digitalOut[led] = 0;

           

            pool.free(message);

        }

 

        ThisThread::sleep_for(10);

    }

}

 

 

void set(Led led, bool state)

{

    Message* message = pool.alloc();

 

    message->led_   = led;

    message->mode_  = Mode::continuous;

    message->value_ = static_cast<float>(state);

 

    queue.put(message);

}   

 

 

void pulse(Led led, float duration)

{

    Message* message = pool.alloc();

 

    message->led_   = led;

    message->mode_  = Mode::pulsed;

    message->value_ = duration;

 

    queue.put(message);

}

 

 

void oscillate(Led led, float period)

{

    Message* message = pool.alloc();

 

    message->led_   = led;

    message->mode_  = Mode::oscillation;

    message->value_ = period;

 

    queue.put(message);

}

 

 

The board looks like this when running the code:

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

  • Sign in to reply

Top Comments

  • neuromodulator
    neuromodulator over 5 years ago in reply to Jan Cumps +2
    Hello Jan, I use to do much more C++ many years ago, before getting into grad school, where I pretty much stopped using C++ for MATLAB and Python. While now getting back to C++ I found that I've forgotten…
  • Jan Cumps
    Jan Cumps over 5 years ago +1
    I'm checking why you have to static cast here. I've been porting the MBED Digitalxxx classes to another platform - requiring static casting points to something sometimes is odd....(it's equivalent to typecasting…
  • neuromodulator
    neuromodulator over 5 years ago in reply to Jan Cumps +1
    Sure! but I'm still very new to Mbed, so I'm not very familiar with it. For instance, C++11 implemented multi-threading, how does it compare with Mbed's (internally, not at the interface level)? If they…
Parents
  • Jan Cumps
    Jan Cumps over 5 years ago

    I'm checking why you have to static cast here. I've been porting the MBED Digitalxxx classes to another platform - requiring static casting points to something sometimes is odd....(it's equivalent to typecasting in C, but in C++ often a sign that a class is used differently than intended).

     

     

    oo musings:

    As an oo fanboy, I would put the 5 LEDs in a container (an array would work) and have an iterator walk over them instead of the for... Loop.

    And have the properties as LED class members instead of a parallel external array,

    and have the iterator call a method of the LED class do the right thing for the properties applicable to that very led.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • neuromodulator
    neuromodulator over 5 years ago in reply to Jan Cumps

    Hello Jan,

     

    I use to do much more C++ many years ago, before getting into grad school, where I pretty much stopped using C++ for MATLAB and Python. While now getting back to C++ I found that I've forgotten way too much and also that the language has evolved a lot, so rest assured that the code that I'm currently writing can be improved a lot. It will take some time for me to relearn the language and catch up with the newest features, so I appreciate your comments...

     

    Now about your comments, I changed a couple of things that are not reflected in this piece of code afterwards (code is around a week old), for instance, I removed statics for an unnamed namespace, which are preferred because they can also limit the scope of classes.

     

    On my code I've always aimed for verbosity and clarity, it takes more time to code but makes code less error prone and easier to understand. I always try to avoid implicit casts, the compiled result is the same, but visually knowing where there is a cast is useful. The reason to prefer C++ casts instead of C casts is that the latter is less explicit. I remember Stroustrup dedicating a few lines of text in his book explaining this.


    I used an array, but an array of pointers to DigitalOut objects. It didn't look neat, but from a quick search I could not find a way to specify the constructor parameters for an array of DigitalOut.

     

    I later joined the LED properties into a single class, separated they looked pretty bad, but this was never a design intent, more like part of how the code began to evolve.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to neuromodulator

    I'm trying to write the same program in OO style, also in MBED. May be great to compare and critique the object way..?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to neuromodulator

    I'm trying to write the same program in OO style, also in MBED. May be great to compare and critique the object way..?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • neuromodulator
    neuromodulator over 5 years ago in reply to Jan Cumps

    Sure! but I'm still very new to Mbed, so I'm not very familiar with it. For instance, C++11 implemented multi-threading, how does it compare with Mbed's (internally, not at the interface level)? If they are equivalent I probably would rather use C++'s, as I always prefer sticking to the language standard.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to neuromodulator

    MBED is a great C++ platform. You'll refresh your skills right away.

     

    Arduino also is a great C++ learner, if you are a library writer.

    A typical Arduino sketch uses objects, but often in a C functional style. You rarely see C++ constructs in an Arduino example sketch.

    For loops, case structures are common in sketches (and good C practice). You often use classes in a sketch but don't define or extend any.

    When you write an Arduino lib, you can learn a lot of C++. Because you define classes there;

    Shout-out to Adafruit, SparkFun and ROHM libs - their OO library code is often beautiful like a poem.

     

    In MBED, you have a chance to go full object oriented. They have encapsulated most functionality in objects and embraced OO as a full playing partner.

    It's worth reading through the code (or stepping through the code if you have a device that supports MBED debugging).

    Just like with Adafruit, SparkFun and ROHM, the code is well written. But they also use very nice OO practices. A wealth of knowledge to learn from.

     

    Disclaimer time:

    You can go full OO with the Arduino IDE and sketches. But I rarely spot it.

    I love C. I love C++.

    No one needs to adapt/adopt OO.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • neuromodulator
    neuromodulator over 5 years ago in reply to Jan Cumps

    Apparently many embedded developers dislike C++. I don't have anything against C, but I enjoy programming in C++ more, specially because I like OOP. Before stopping to program in C++ I was playing with template metaprogramming, which was kind cool. Templates are kinda nice but I feel they can make the code much harder to read, plus they require a lot of knowledge of the language to effectively use them. I still need to learn a lot of the new C++ features, the language sadly has gotten even more complex than what it already was. I think part of C++'s complexity is because of its backward compatibility to C.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to neuromodulator
    Apparently many embedded developers dislike C++. I don't have anything against C, but I enjoy programming in C++ more, specially because I like OOP

    The same for me. I think C is a great language. The electronic load firmware is fully written in C. I claim it's very tidy C image.

    I like OO, but also think it adds. I don't see it as a fancy thing but as an evolution in software development.

    It needs a change adaption of mind, but it doesn't require to abandon any knowledge.

     

     

     

     

    I still need to learn a lot of the new C++ features, the language sadly has gotten even more complex than what it already was. I think part of C++'s complexity is because of its backward compatibility to C.

     

    Nothing added to the language is a break with the past. The additions have taken away some weaknesses - in particular in those cases where C++ was too verbose.

    But you can just kick it off from where you left. Then if you want, step by step check what's added, check why it's added, then embrace, ignore or reject image.

    It's good to check language evolution, because they aren't done for the kick of it. They make sense.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • neuromodulator
    neuromodulator over 5 years ago in reply to Jan Cumps

    I agree!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube