Arduino Tutorial - How the code structure works

Would you like to help?
Share your walkthrough tutorial with others
User avatar
Posts: 1426
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City
PostPosted: Sun Jun 02, 2013 7:06 am
Here's some code I generated with the Wizard.

Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <ReefAngel.h>

////// Place global variable code below here


////// Place global variable code above here


void setup()
{
    // This must be the first line
    ReefAngel.Init();  //Initialize controller
    ReefAngel.AddStandardMenu();  // Add Standard Menu

    // Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = Port3Bit;
    // Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = 0;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = 0;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = 0;
    // Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;
    // Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 869 );


    // Ports that are always on
    ReefAngel.Relay.On( Port3 );
    ReefAngel.Relay.On( Port4 );

    ////// Place additional initialization code below here
   

    ////// Place additional initialization code above here
}

void loop()
{
    ReefAngel.StandardFan( Port1,771,781 );
    ReefAngel.StandardHeater( Port2,751,761 );
    ReefAngel.DosingPumpRepeat( Port5,0,240,120 );
    ReefAngel.Wavemaker( Port6,60 );
    ReefAngel.StandardLights( Port7,9,0,19,0 );
    ReefAngel.StandardLights( Port8,9,0,19,0 );
    ReefAngel.DosingPumpRepeat( Box1_Port1,0,360,120 );
    ReefAngel.DosingPumpRepeat( Box1_Port2,60,360,120 );
    ReefAngel.SingleATO( true,Box1_Port3,60,0 );
    ReefAngel.PWM.SetDaylight( PWMSlope(9,0,20,0,0,100,60,15) );
    ReefAngel.PWM.SetActinic( PWMSlope(9,0,20,0,0,100,60,15) );
    ////// Place your custom code below here
   

    ////// Place your custom code above here

    // This should always be the last line
    ReefAngel.ShowInterface();
}



Lets go over it line by line.

The first part:

Code: Select all
#include <ReefAngel_Features.h>
#include <Globals.h>
#include <RA_Wifi.h>
#include <Wire.h>
#include <OneWire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <InternalEEPROM.h>
#include <RA_NokiaLCD.h>
#include <RA_ATO.h>
#include <RA_Joystick.h>
#include <LED.h>
#include <RA_TempSensor.h>
#include <Relay.h>
#include <RA_PWM.h>
#include <Timer.h>
#include <Memory.h>
#include <InternalEEPROM.h>
#include <RA_Colors.h>
#include <RA_CustomColors.h>
#include <Salinity.h>
#include <RF.h>
#include <IO.h>
#include <ORP.h>
#include <AI.h>
#include <PH.h>
#include <WaterLevel.h>
#include <ReefAngel.h>

These are instructions to the compiler. This says "Before we start with my program, go get all this stuff and include it in." This is where our RA functions are kept. When we say "Hey, ReefAngel, do this" most likely it's something stored in these files.

Next part:

Code: Select all
////// Place global variable code below here


////// Place global variable code above here


Anything after // on the current line is ignored. It is a comment for the reader's eyes. The controller couldn't care less about it. Note there are lots of extra /'s in these lines. They're for aesthetic purposes only. They're ignored too.

Another way to comment is like this:

Code: Select all
/* These symbols
    Make Comments
    Out of Everything
    Between Them.
*/


Note that if you just put in "/*" without "*/", it will comment out the rest of your code! In the RA Arduino editor, stuff that is commented is greyed out. If your code is greyed out when it shouldn't be, then check for this.

Code: Select all
void setup()


Now we're getting to the fun stuff. This starts a function called setup. It's one of the two functions you must have in Aruduino to have a valid sketch (Arduino's word for program).

void means that when we call this function, we don't expect it to tell us anything back. It's a little out of place here since we never really call setup, it is automatically run once when the program starts up. The empty () means we aren't sending any data to it. Again, kind of extra in this case.

Next, we have {. This starts a section of code. In this case, it's the beginning of setup(). Every function will have a { at the beginning and a } at the end. In addition, you may have other sets of these inside the function. An "if" statement is a good example of this. Again, they just define a section of the code.

Code: Select all
    ReefAngel.Init();  //Initialize controller


This line says call the function ReefAngel.Init, and don't send it anything, hence the empty parentheses. The ";" marks the end of the line, and the // is for the comment that is nice for us to read but ignored by the program.

Code: Select all
    ReefAngel.AddStandardMenu();  // Add Standard Menu


Same stuff here.

Code: Select all
// Ports toggled in Feeding Mode
    ReefAngel.FeedingModePorts = Port3Bit;


This one is a little tricky. This sets the ports turned off by feeding mode. In this example, it's port (relay) #3, which is my skimmer. The Port3Bit business is advanced stuff that I don't have a good enough grasp on to teach, so just know that that's how it works. Again, notice the ";" at the end of the line.

Code: Select all
// Ports toggled in Water Change Mode
    ReefAngel.WaterChangePorts = 0;
    // Ports toggled when Lights On / Off menu entry selected
    ReefAngel.LightsOnPorts = 0;
    // Ports turned off when Overheat temperature exceeded
    ReefAngel.OverheatShutoffPorts = 0;


Same stuff. On my setup I don't use these things, so they're set to 0, meaning no ports are set for these.

Code: Select all
// Use T1 probe as temperature and overheat functions
    ReefAngel.TempProbe = T1_PROBE;
    ReefAngel.OverheatProbe = T1_PROBE;


This sets the TempProbe and the OverheatProbe to the value stored in T1_PROBE. T1_PROBE is defined in one of the #includes as the first temperature probe.

Please note that everything is CaSe SeNsItIvE! T1_PROBE is not the same as t1_probe. Capitalization is important.

Code: Select all
// Set the Overheat temperature setting
    InternalMemory.OverheatTemp_write( 869 );


OK, a little more action here. This calls a function that writes the internal memory overheat and tells it 869. This is actually our overheat temperature of 86.9F. RA stores it as 869 because it takes up a lot less memory than 86.9.

A note on function names. You can name functions just about anything you like. Writers will use "." and "_" as part of the function name. The "." is used to denote different functions in a group. Like ReefAngel.TempProbe and ReefAngel.OverheatProbe, both parts of the ReefAngel group. The "_" is used intstead of spaces, which are not allowed.

Code: Select all
// Ports that are always on
    ReefAngel.Relay.On( Port3 );
    ReefAngel.Relay.On( Port4 );


These call the function ReefAngel.Relay.On and tell it to turn on Port3 and Port4. There is also a corresponding function called ReefAngel.Relay.Off. Notice the clever use of periods to make things neat and tidy.

Finally,

Code: Select all
  ////// Place additional initialization code below here
   

    ////// Place additional initialization code above here
}


More comment lines, followed by the all-important "}". This is the end of setup().

Part 2 to follow.

--Colin
User avatar
Posts: 1426
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City
PostPosted: Sun Jun 02, 2013 8:01 am
Part 2. The loop.

Code: Select all
void loop()
{


So here we have loop(). This is the other required function in an Arduino program, the first being setup(). Unlike setup(), which is only run once (such as when you turn on the power to the RA or reset it or load a new program), loop() is run over and over as long as the power is on. Also note we start with a "{".

Code: Select all
    ReefAngel.StandardFan( Port1,771,781 );


This sets our fan. We're passing information (technically called "arguments") to the function. The function knows to expect the following: The port (relay) to use, the temperature to turn off on (771, or 77.1, remember we store as an integer for memory savings), and the temperature to turn off on (78.1). If we were using the internal memory instead of hardcoding our temps, we can just pass the Port1 and RA knows to look in the internal memory for the temps, like this:

Code: Select all
    ReefAngel.StandardFan( Port1);


This works for any of the settings in this section. If you're using the Wizard and select the internal memory option, you will get two sketches to upload. The first one sets the memory locations (heater/fan temps, lighting times, etc) and the second one is the actual program.

The heater line works just like the fan line.

Code: Select all
    ReefAngel.DosingPumpRepeat( Port5,0,240,120 );


This function runs a dosing pump on a repeating schedule. Port5 is the port, 0 is the offset, 240 is how many minutes between cycles, and 120 is how many seconds to run. So every 240 minutes (4 hours), Port 5 switches on for 2 minutes. This is actually my Swabbie skimmer neck cleaner. I've used the dosing pump command because it is ideal for what I need.

A note on times. Everything is based off of midnight. So when I tell RA to run this dosing pump every four hours, it means midnight, 4 am, 8, noon, 4 pm, 8 pm, and midnight. If I want to change the start time, I can change the offset from 0 to some other number (in minutes). If I change the 0 to 60, for example, then it would run at 1 am, 5 am, 9 am, etc.

Code: Select all
    ReefAngel.Wavemaker( Port6,60 );


Wavemaker on Port6, 60 seconds on, 60 seconds off.

Code: Select all
    ReefAngel.StandardLights( Port7,9,0,19,0 );


This for light scheduling. It works like this:

ReefAngel.StandardLights( port, start time hour, start time minute, end time hour, end time minute)

In 24 hour format. So this command will run our lights from 0900 (9 am) to 1900 (7 pm).

Code: Select all
   ReefAngel.StandardLights( Port8,9,0,19,0 );
    ReefAngel.DosingPumpRepeat( Box1_Port1,0,360,120 );
    ReefAngel.DosingPumpRepeat( Box1_Port2,60,360,120 );


More stuff we've seen before. Note the 60 minute offset on the second dosing pump. This is useful if you are dosing 2 part solution and lets you dose the calcium and alk parts an hour apart. Also note the funny port names (Box1_Port1). These are outlets on an expansion relay box.

Code: Select all
    ReefAngel.SingleATO( true,Box1_Port3,60,0 );


Sets up the ATO. I use a single float switch on mine. The interesting thing about this line is our friend "true". true and false are called "boolean" values. You can replace them with 1 for true and 0 for false. In this case, ReefAngel.SingleATO knows that true in that first position means use the Low ATO port for the topoff. Box1_Port3 is an outlet on my expansion box. 60 means a 60 second timeout, and the 0 has to do with how often the pump is allowed to run. 0 means no limit.

First of all a clarification: This isn't the actual code I use, it's just something I popped out of the Wizard using settings similar to mine. I don't actually control my lights with the StandardLights function as shown above. I use the dimmer functions exclusively to ramp my lights up and down. When they reach the low value, they just dim to off. This is more like the code I use for my LED's:

Code: Select all
 ReefAngel.PWM.SetDaylight( PWMSlope(9,0,20,0,0,100,60,15) );
    ReefAngel.PWM.SetActinic( PWMSlope(9,0,20,0,0,100,60,15) );


ReefAngel.PWM.SetDaylight and SetActinic expect a number from 0 to 100 (percent on). Like this:

ReefAngel.PWM.SetDaylight( some number from 0 to 100 indicating brightness)


So what is all that funny PWMSlope stuff doing there where a number should be?

It's a function within a function! SetDaylight expects a number. The number we are giving it is the one returned by the PWMSlope function. PWMSlope works like this:

PWMSlope(start hour, start minute, end hour, end minute, start value, end value, duration, default)

The times work like StandardLights. The start value is the low part of the dimming cycle, the end value is the high part of the dimming cycle, duration is the number of minutes over which the dimming cycle progresses, and default is the value returned if we are not in the defined time frame.

So in this case, I want the lights to come on at 0% at 9 am, progress to 100% over an hour, run at 100% until 7 pm (20 minus an hour for the sunset), then dim back down to 0% over another hour to shut off at 8 pm (2000 hours).

So this:

Code: Select all
PWMSlope(9,0,20,0,0,100,60,15)


Turns into a number between 0 and 100 depending on the time of day.

Code: Select all
////// Place your custom code below here
   

    ////// Place your custom code above here

    // This should always be the last line
    ReefAngel.ShowInterface();
}


More comments, the required last line to show the screen, and our closing "}" to end our loop section.

Hope this helps,

--Colin

Posts: 12270
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Sun Jun 02, 2013 8:03 am
Thanks for the tutorial!!!
I've made this a sticky :)
Roberto.
User avatar
Posts: 5349
Joined: Fri Jul 20, 2012 9:42 am
PostPosted: Sun Jun 02, 2013 8:28 am
Awesome work!

One thing i'd like to point out in Part 1 when you talk about "groups" and having things separated by periods. This is called a "class" and the periods represent the variables and functions that are part of the "ReefAngel" class.

When I get some time I'll try and write up something to go into the Port1Bit pieces :)

Thanks for starting this!

Posts: 329
Joined: Fri May 17, 2013 1:35 pm
PostPosted: Sun Jun 02, 2013 8:47 am
this is what ive been looking for.....break down of how codes work and what means what. i will have to take some time and read this THANKS!!! i think my eyes are starting too uncross.lol
dont forget this link its helpful aswell.
http://www.introtoarduino.com/downloads ... noBook.pdf
Image
User avatar
Posts: 2743
Joined: Fri Mar 18, 2011 6:20 pm
Location: Illinois
PostPosted: Sun Jun 02, 2013 9:24 am
Nice write up. A simple walk through of the code without getting too technical. Great Job!!
User avatar
Posts: 1426
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City
PostPosted: Sun Jun 02, 2013 1:29 pm
lnevo wrote:Awesome work!

One thing i'd like to point out in Part 1 when you talk about "groups" and having things separated by periods. This is called a "class" and the periods represent the variables and functions that are part of the "ReefAngel" class.

When I get some time I'll try and write up something to go into the Port1Bit pieces :)

Thanks for starting this!


I knew there was a fancy, cityfied word for it! Thanks, Lee.

I'm no professional programmer, but as a RN I'm used to explaining complicated things in understandable terms. I'm glad I can help!

--Colin

Posts: 4
Joined: Wed Mar 20, 2013 11:38 am
PostPosted: Tue Sep 10, 2013 12:49 pm
Thank you for taking the time to break it down for newbies like me. I'm basically a copy and paste "programmer", i find the code i need, from code that someone else volunteered and copy it and past it on my own. This definitely will take me to the next level.

Mario
Image
User avatar
Posts: 1426
Joined: Fri Mar 29, 2013 3:51 pm
Location: Oklahoma City
PostPosted: Wed Sep 11, 2013 8:38 am
You're welcome!

--Colin

Posts: 62
Joined: Mon Feb 24, 2014 9:38 pm
Location: Sydney, Australia
PostPosted: Wed Mar 12, 2014 6:52 pm
Hi Colin,

Thanks for the great write up, now I understand the basic part of it.
One question I have is regarding the first "include" part. I assume that those are the files that are unique for the RA, and defines how they are all wired into the arduino board etc, and what kind of input/output/variables you get from each function. Are they described in any more detail anywhere, for instance the "tempsensor" file, what is coming out of it etc, or have I completely misunderstood this?
Next

Return to Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest