Author Topic: How to program a UNO  (Read 3962 times)

0 Members and 1 Guest are viewing this topic.

OperaHouse

  • Hero Member
  • *****
  • Posts: 1309
  • Country: us
How to program a UNO
« on: May 01, 2012, 11:21:53 AM »
INTRODUCTION
I have a complex solar system at my camp that has grown over the years.  It consists of a car battery and about 800W (and growing) of solar panels to run primarily a chest freezer as a dump load. I hate batteries.  The one I use is out of the vehicle I leave at home for five months and is only used to provide the 90A starting surge of the fridge.  The collection of voltage sensors and timers has worked well over the years but on good days I have excess power that is just wasted.  It was finally time to do some smart load shifting.   I was doing some retail store animation and used an ARDUINO UNO as the controller.   These are very powerful and super cheap (as low as $16 for a 2011 version from China).  I decided to make this a demonstrator project where battery regulation and smart load shifting are done with software and very simple hardware.  The following posts will be snippets of typical code from the project. My system won't be your system.   These routines are to be used as basic building blocks. Hopefully it will be understandable to those who have not tried programming and encourage them to try it.  The programmer is free to download at arduino.cc and allows you try programming  before buying any hardware.   

The routines shown are tested for basic functionality.  Whether they are suited for the purpose intended will take a couple months to determine.  Hardware schematics will be posted later after testing is done.  Every line of code has lots of comments to help with understanding.  In some cases things were done the long way or were even unnecessary to serve as a teaching point.  There are always multiple ways to obtain the same result.  Most control applications are fairly simple and you can learn to program.  Like any language syntax and sentence structure are important.   The computer won't fill in things that are missing.   Remember dialing long distance and this voice says you need to add a one before the number.  Well if the computer knew that, why didn't it just add the one instead of making you redial everything.
 
This is the 2011 version UNO. The latest R3 version costs more but does not add any additional functionality.   Note that connections are typically made by pushing in a thin wire or lead of a 1/8 watt resistor into a socket strip.  It is a good idea to make connections  to inputs and  outputs with 300 ohms or higher.  This will prevent burning out a pin if it should be connected to power or ground.   To the right is a connector made from  a five pin strip cut from a circuit board.  Hot melt glue and shrink tubing provide the strain relief.   There arefour mounting holes on the board.   Too small for stock of snap in nylon mounts and traces are too close for anything metal.   I just used a half inch block of hard polyethylene foam as a spacer and used hot melt glue. 
In addition to the factory site some additional instruction can be found at.

http://www.instructables.com/id/Intro-to-Arduino/



OperaHouse

  • Hero Member
  • *****
  • Posts: 1309
  • Country: us
UNO DIAGNOSTIC SCREEN
« Reply #1 on: May 01, 2012, 11:29:46 AM »
DIAGNOSTIC SCREEN
The first sample of code is a diagnostic screen.   This may seem to be a strange way to start but this is a must for any program.  Often that logical path you dreamed up doesn't work out as intended.  Displaying key variable values allows you quickly get sections of code working.   With the USB cable connected, serial data can be sent to the screen.  To view that data go into TOOLS and select  SERIAL MONITOR.

When the variables are defined at the beginning of the program the initial screen is selected.  Each loop of the program will print a new line of data.  If a new keyboard character is recognized a different screen can be displayed.  This section of program can be repeated for other characters.

The practical limit is four to six variables displayed in the small insert box.  Beyond that you won't remember what the numbers represent.  Note print is used to send out each variable and then a TAB character ‘\t'  to space the data.  At the end a println is used which automatically will add a NEW LINE character.   Generally floating math should be avoided in the program because it is slow.  Dividing by a floating point number in the print statement is a gimmick to display the value in understandable terms.  The default is two decimal places.
The keyboard read can also be used to reset a variable or force a condition like an output.    All you really need to learn is the IF statement.    HELP is only a click away in REFERENCE.  Every operator is defined.  Try to make all your decisions one liners that stand on their own.   Putting more than one additional IF within an IF can become confusing.  Get into the habit of using the VERIFY after  every one or two lines of code.    VERIFY is a pre compiler that will point out errors.   At least it gets you close.  Sentence structure is important.  The editor is very helpful by using colors and highlights.


// This section sends out serial data contained in the program. It has no actual functional use in the program.  It can be viewed by using SERIAL MONITOR
 // in TOOLS when the ARDUINO programmer is running.  The program can run without any serial monitor connected.  Some diagnostic section like this should be   
 // included in all programs.  It will save a lot of time in the development of programs.
 
 if (Serial.available() > 0) kbd = Serial.read();                              // look for and get keyboard character to change diagnostic screen 
                                                                               // kbd is the character returned from keyboard
     
 if (kbd == 'R' || kbd == 'r' )                              // if R or r  RESET variables
     {                                                                         // { indicates start of code routine
     minutes  =  0;
     startEQ = 0;
     }
   
  //                                                       BATTERY DEBUG SCREEN
  if (kbd == 'b' || kbd == 'B' || keyboard == 'B')                              // if B or b send out BATTERY debug screen
                                                                                // The double vertical line (||) is the LOGICAL OR symbol IF any of these are TRUE.
     {                                                                          // { indicates start of routine
      keyboard = 'B';                                                           // retain keyboard value otherwise it will be lost
      Serial.print(battery / 999.9);                                            // battery voltage.  Division creates 2 decimal place voltaage
      Serial.print('\t');                                                       // tab to next column
      Serial.print(AI0);                                                        // battery voltage raw A/D debug value
      Serial.print('\t');                                                       // tab to next column
      Serial.print(minutes);                                                    // Minutes the microprocessor has been on     
      Serial.print('\t');                                                       // tab to next column
      Serial.print(startEQ);                                                    // Time that Equalize Battery was started
      Serial.print('\t');                                                       // tab to next column
      Serial.print(panel / 999.9);                                              // Solar Panel #1 voltage   Division creates 2 decimal place voltaage
      Serial.print('\t');                                                       // tab to next column
      Serial.print(outcharge);                                                  // Output of PWM DRIVE to charge battery from Panel #1 (0-200)
      Serial.print('\t');                                                       // tab to next column
     
                                                                                // NOTE: printlin is used this time instead of print.   println adds a new line character
                                                                                // automatically after the data string so the next set of data is on a new line.  The
                                                                                // Auto Scroll box in the SERIAL MONITOR tool can be unchecked to freeze the screen.
 
      Serial.println ('B');                                                     // B is shown to identify this is the battery screen
      }                                                                         // } indicates this is the end of this code routine
     

OperaHouse

  • Hero Member
  • *****
  • Posts: 1309
  • Country: us
UNO ANALOG INPUTS
« Reply #2 on: May 01, 2012, 11:32:36 AM »
ANALOG INPUTS
The UNO has six analog inputs designated A0 t0 A5.  These go from 0 to 1025 counts or 4.9 mV per count.  A resistive voltage divider allows scaling to higher voltages.  Use 3.3V as the nominal target voltage for the divider for approximately 675 counts.   This will allow you to use the 3.3V pin of the UNO for stand alone testing when developing code.  Just connect a 300-2K resistor from that pin to the analog input.  Any signal has noise.  Remember……Order emerges out of chaos.   Add enough of these values together and things will be pretty stable.   The running average method I use has the additional feature of scaling the number close to an engineering value.  Keep in mind an interger can be negative and there is an upper limit to the value.  Exceed that value and the number will roll over giving an unexpected result.  Do some sample math before you start to see how large the numbers get.   Numbers too small are also bad.  Interger division truncates the value.  Try to make numbers as large as possible before dividing.  Instead of dividing by 100 to make a standard engineering unit like a watt, divide by 10 to make a deciwatt within the program.  Avoid using floating point math.
MAP is a mapping or table conversion function that converts one number to another through interpolation.  The example used here is temperature based on a diodes voltage.  As diode voltage goes up the temperature goes down.   If you know two points, map does all the work for you.
CONSTRAIN  limits the upper and lower value of a variable.

// This section reads the analog signals.  Range is 0 to 5V DC or 0 to 1023 counts or 4.9mV per count
  AI0  = analogRead (0);                               // Anolog In.  Read the battery voltage on PIN #A0
  AI1  = analogRead (1);                               // Anolog In.  Read the panel voltage on PIN #A1
  AI2  = analogRead (2);                               // Anolog In.  Read the solar voltage on PIN #A2
  AI3  = analogRead (3);                               // Anolog In.  Read the diode voltage on PIN #A3 to
// obtain Water Temperature
  AI4  = analogRead (4);                               // Anolog In.  Read the diode voltage on PIN #A3 to
// obtain Cooler Temperature
 
  // This section takes a running average of the signal. Not really an average, it is the sum of N readings.
  // One average of N samples is thrown out and a new sample is
  // added in.  At first it may not seem like the math works out but it does.  Enter a fixed number and
  //  the final value will converge on that value times the number N.
  // Not only does this average out the noise but it is a very convenient way to scale up the number.
  //  Adding up 20 A/D samples closely approximates battery voltage in mV.
  // Just as easily that number can be made 19 or 21 to get you in the ballpark. Then you only need
  // a slight resistor trim.  Converting early to understandable engineering
  // units makes the program much more understandable.
 
 battery = battery - battery / 20;                     // Sum the readings by subtracting one average reading
                                                                              //    13.5V = 3.3V
 battery = battery + AI0;                                  // Add latest A/D reading

 panel   = panel - panel / 48;                          // Sum the readings by subtracting one average reading
   //       32V = 3.3V
 panel   = panel + AI1;                                     // Add latest A/D reading
 
 heater  = heater - heater / 17;                     // Sum the readings by subtracting one average reading
                  //      80V = 3.3V
 heater  = heater + AI2;                                  // Add latest A/D reading
 heatervolt = heater / 100;
 
 Wtemp  = Wtemp - Wtemp / 10;                // Sum the readings by subtracting one average reading before conversion to F
 Wtemp  = Wtemp + AI3;                                // Add latest A/D reading
// NOTE: Ctemp calculation is located in the refrigerator section so it can be easily removed from
// the program.
 
 
 // Convert the digital input (times ten) into degree F using map function.  Data conversions are easy
// using the map function of the ARDUINO
 // Format for this is:   map (input value, high temp value, low temp value,  high temp of 212
 //  degrees, low temp of 32 degrees)
 // Your A/D values may vary due to diode type and current through diode.  Get values using
 // ice bath and boiling water
 // If you know air temp and get value in ice bath, high temp value may be determined by
 // changing value untill the correct air temp
 // value is obtained. No need to burn your figures.  NOTE: diode has a lower voltage at
 //  higher temperature
 // Constrain function keeps data values within the known values used by map function.
 
 
 // Wtemp = constrain(Wtemp, 2600, 3700);                 // limits range of sensor values to between
         //2600 and 3800
// FW = map(Wtemp, 2584, 3654, 212, 32);                  // For THREE small signal diodes with 10K pullup
        //  to +5
 // map (X, low, high, 212F, 32F) FW is water temp in degrees F
                                                                         // 3654 is measured low in ice bath

 Wtemp = constrain(Wtemp, 3000, 5000);                   // limits range of sensor values to between 3000 and 5000
 FW = map(Wtemp, 3100, 4867, 212, 32);                   // For FOUR small signal diodes with 10K pullup to +5V
 // map (X, low, high, 212F, 32F)  FW is water temp in degrees F
                                                         // 4867 is measured low in ice bath
                                                         // 4520 is measured at 68 degrees


GoVertical

  • Hero Member
  • *****
  • Posts: 691
  • Country: us
Re: How to program a UNO
« Reply #3 on: May 02, 2012, 07:37:38 AM »
Hi, thanks for posting your project. I look forward to seeing your circuit. Well written.
Learn from the past, live in the present, plan for the future
kilroyOdin is not here ;)
SEMPER FEROX

OperaHouse

  • Hero Member
  • *****
  • Posts: 1309
  • Country: us
Re: How to program a UNO
« Reply #4 on: May 02, 2012, 10:31:59 AM »
Sorry, when it goes from one word editor from another that everything gets clobbered.  I think you will find my hardware approach quite different from what you have done.  Don't want to post that till it is fully developed.

SparWeb

  • Global Moderator
  • Super Hero Member Plus
  • *****
  • Posts: 5452
  • Country: ca
    • Wind Turbine Project Field Notes
Re: How to program a UNO
« Reply #5 on: May 15, 2012, 03:09:12 PM »
O.H.,
I will be interested to watch this evolve.  My experience is all with the Picaxe, but I have an Arduino in its box, waiting for the day I have time to start using it (was thinking robotics to amuse my kid).

You probably already know, OH, but for completeness of this thread, I could add that Arduino's can be set up with "shield" boards, and they are conveniently layed out for this.  You can either buy one or make one of your own, fit for purpose.  The shield board is just the interface, where you put the connectors, resistors, voltage dividers, filters, etc etc. to clean up the input signals.  Then the shield board snaps down on the input terminal blocks of the Arduino, and voila, a modular computer interface.

The "factory" info is actually very open-source and community based (like this forum).  There are a lot of searchable ideas for the Arduino out there, which is what attracts me to using them (if I can ever get the time!).
No one believes the theory except the one who developed it. Everyone believes the experiment except the one who ran it.
System spec: 135w BP multicrystalline panels, Xantrex C40, DIY 10ft (3m) diameter wind turbine, Tri-Star TS60, 800AH x 24V AGM Battery, Xantrex SW4024
www.sparweb.ca

OperaHouse

  • Hero Member
  • *****
  • Posts: 1309
  • Country: us
Re: How to program a UNO
« Reply #6 on: May 15, 2012, 04:19:49 PM »
Those shield boards kinda destroy the whole cost value of using one of these.  Just as easy to  breadboard on the side by sticking a couple resistors in the sockets.  With the 490hz PWM it is easy to high side drive a ET with just an opto isolator up to 85% duty cycle.  Just don't need more than that.  Here is the airplane control board using serial communication to a opto22 driver board.  I have a few opto22 Majic boards I want to try.  The real value is the complex logic you can do with just 20 lines of code.