Sailcode Alpha 1 - first alpha, waiting for parsing to be ported

Sailcode Alpha 2 - the complete ported code, including all sailing functions. parsing imported, serial ported; some glitches with parsing; biggest ones are that the buffer fills faster than we read it; and the parsing cant handle when data is returned with nothing between commas

Sailcode Alpha 3 - systems test code, using only the parsing and serial code from sailcode alpha 2 and the pololu control to turn a motor according to the heading. no sailing logic functions.

Reliable_serial_data.pde - function to be used in Wind and Compass building on the simple method of reading from the serial port; empties the serial buffer and error checks the data

Sailcode Alpha 4 - a copy of alpha3 created when moving files around when opening with Arduino0022 software

Sailcode Alpha 5 - a merge of alpha3 with reliable serial data; contains the change structure of alpha3

Sailcode Alpha 6 - major update to alpha5 everything uses structs, sailing functions rewritten

To doEdit

  • Fix the basics of the sailcode, which are commented
  • Look into interrupts - looked into, refuse to work with current sailcode for unknown reasons
  • Look into overwriting the compass/PB100 EEPROM
  • Check out the version control software on Version Control, there's a list of tasks on both Launchpad and Google Code
  • Look into RTOS

Current Functions in Sailcode 6Edit

The below section is for maintaining documentation of the existing sailcode,

Function Description Comments


Called by loop()


This function allows the user to modify the current actions of the boat to run a specific program or to get basic data about the boats location and the present conditions. It is essentially a large switch-case looking for an input character. The menu returns a value which is then used in loop() to set the boat on a specific course. Presently the menu can: input waypoints, view waypoints, clear waypoints, call sailCourse, sail, sailToWapoint, stationkeep, retrieve wind and compass data, toggle rudder direction, get a gps coordinate, switch to keyboard control, switch to RC control for either rudder or sails and rudder, and perform diagnostics. So this is the all doing all seeing menu code. It is still in testing, only the commands marked with a star are thought to work correctly.


Called by loop()

Calls sailToWaypoint GPSdistance

Function checks if the boat is near the current waypoint, updates its next waypoint if it reached the target on a course set up in the menu. Has not been fully tested,

sailToWaypoint( struct points waypoint)

Called by loop(), sailCourse

Calls getWaypointDirn, checkTack, tack, sail

This performs a check to see if the boat is on course. It finds the waypoint direction, checks if it is tacking, or needs to tack, or if it can just sail. This is the heart of the sailing logic, it checks to see which of the two basic sailing routines to follow, sailing, or tacking

sail(int waypointDirn)

Called by loop(), sailToWaypoint

Calls getWindDirn, between, getCloseHauledDirn, rudderControl, sailControl

Sails toward a direction passed in. If the direction is upwind it will try to sail closehauled as far up as possible. It then calls sailControl and rudderControl to adjust for te chosen direction. This used to be straighsail, but now takes care of both sail and rudder control, and can not sail upwind


Called by Sail()

Calls setSails

Checks to make sure that the boat is not heeling too much, and then sets the sails proportionally to the amount the angle of the wind, if closehauled set all in Might want to average the error to get smoother performance


Called by Sail()

Calls setrudder

Sets the rudder proportionally to the amount of direction error between the current direction and the desired direction. Currently it divides the error by 4. This may be changed to a PID, or averaged for smooth response

checkTack(int corridorHalfWidth, struct points waypoint)

Called by sailToWaypoint

Calls getWindDirn, between, GPSDistance

CheckTack determines if a tack is needed, first it checks if the current heading is closehauled. Next it checks is travelling away from the corridor, so it only tacks toward the mark. Finally it checks if it needs to tack from being outside of the corridor, or if it is past the layline. This is the basic check for tacking, it still needs to be water tested


called by sailToWaypoint

Calls getOutofIrons, getCloseHauledDirn, setrudder, setMain, setJib

This is the code is responsible for the boats tacking. It sets the side of tacking, then, based on side it sets the rudder to a side, lets jib out, main in, until the wind angle switches sides, in which case it releases the main and pulls in the jib. If the boat is tacking for too long it will call get out of irons. When the boat has turned far enough it will get out of the tacking routine. The tacking code has not been fully tested and remains a critical component in sailcode, it needs tweaking

GPSdistance(struct points location1, location 2)

Finds the distance between two coordinates in metres suspect that this may not be working quite right
getWaypointDirn(struct points waypoint) Finds the direction to a waypoint from the boat relative to north.
getCloseHauledDirn() Finds the closehauled direction for the boat. It takes the current wind direction heading relative to north and add or subtracts the tacking angle depending on the side of the wind.
getWindDirn() Returns the compass direction of the wind. It takes the wind angle relative to the boat and adds it the the compass heading, and then normalizes it.
transmit(void) This function sends data to the labview ground station. It parses the data from a number of globals into a form that can be quickly ready by the grounds station. care has to betaken to not overlengthen this function, as this will mess up the groundstation

Guidelines to PortingEdit

  • Ported code must be commented as much as possible... explain it for the next person please :D
  • indent with a tab
  • start at highest level functions and use dummy functions to get high level compiling and working; and fill in the lower level functions iteratively
  • do not change the reference file test4.c
  • one person will work on the main function and go downwards
  • some people can work from the bottom up
  • Once a complete function is ported and tested, upload it to dropbox
  • Use the arduino emulator to test code: elec299 course page
  • Put your name in the Comments/progress box of the table for the function you are working on
  • As you work (or at LEAST at the end of a session) fill in comments about main things you changed, what is working, what is not working

Variable (not flexible) GuidelinesEdit

  • ALL CAPS VARIABLES are constants
  • Caps On First Letter variables are globals
  • global variables should not have their names changed
  • functions should not have their names changed
  • lower case variables are local variables to a function
  • variables should be named variableOne with capital on second word if there are two words in a variable

Using the ELEC299 SimulatorEdit

See the Compilers and Simulators page.

Porting 2009's code to ArduinoEdit

On the dropbox account there is a pdf in Software 2010/11 -> Old Code folder called Complete.pdf. This is the documentation of the 2009/2010 code, and might be useful for reference.


  • If necessary, extend TinyGPS to include all the NMEA sentences we need; this will save memory over using strtok, sscanf for parsing
  • Move to an interrupt-driven program; this should speed up execution time

Function Change to Make Progress & comments Make available in Menu?



none compiled maybe



change printf, scanf; update string functions for waypoints or change waypoints to be stored in an array repeatedly prompting for the number of waypoints; some sort of error yes



this goes to the zigbee shield, for now to the serial monitor; all done printf -> Serial.print() when called for first compile run; needs to just be copy/pasted; however in Arduino cant printf("The %d person's account is %f", int1, float1); instead have to insert each variable as in Serial.print("The "); Serial.print(int1); Serial.print(" person's account is ");.... no

scanf -> change name to scanln to support ELEC299 testing

L H fortesting

write a function to scan a full line (not just a single character) from a serial port (but need to decide on formatting - always return a string?)



check out this link:

also the [Reading and Parsing Data] page, under software



H, L

most of this can go, replace with a serial command to pololu pololu is working; trim down the pololu code to the basics and put it in setrudder, as well as in setup; seems good yes
targetang fine compiled no
corridor2 fine compiled no



need to make sure theres a buffer range of acceptable angles (ie dont keep making tiny adjustments) - try to turn it enough to correct for the error in the angle (this is PID) compiled; but needs future improvement no



the whole waypoint strategy needs to just be changed, either to a linked list (Waypoint_List) or an array; none of this storing in a string stuff compiled; changed to just retrieve a waypoint from the global waypt[i] array no
sail fine compiled; no changes required yes



rudder control should be PID compiled; but needs future improvement yes



rudder control should be PID compiled; but needs future improvement yes



rudder control should be PID compiled; but needs future improvement yes



comment; very cryptic right now; do we use this? compiled; replaced atan2 (what was atan2?); replaced pow no



this doesnt seem like it would work; check against 2007 code; timer? compiled; but needs future improvement yes



most of this can be cropped out; reads and parses compass input from serial

Reading and Parsing Data has links on using TinyGPS; could extend this to save memory

could use future improvement; presently calls Parser(); needs to incorporate reliable_serial_data.pde


most of this can be cropped out; reads and parses wind sensor (weather station) input from serial

Reading and Parsing Data has links on using TinyGPS; could extend this to save memory

could use future improvement; presently calls Parser(); needs to incorporate reliable_serial_data.pde

datavalid fine


Parser L just needs a general cleaning up; replace with an NMEA library?

ported using strtok; assumes error-checked NMEA string; needs more error checking

poll fine. but should we use this? dummy no



fine... I think... make sure this is doing what it should rewrite this no
initportW not needed; just do it in Wind/setup
SerialPort,CB not needed
writeport modify
getbaud not needed?? just do the equiv fn where you need the baud rate
readport not needed? just do the equiv fn where you need to read from a port
initportC not needed; just do it in Compass

Function BuildingEdit

The following sections should be documented when writing functions: (copy this template to a section about the specific function)

Background InformationEdit

What does the function do; why is it used

Options ConsideredEdit

A pros/cons for each option should at least be documented; more complicated decision matrices are also possible.

List of design criteria

  • fast
  • efficient
  • clear and easy to modify
  • modularized
  • appropriate complexness for problem
  • others appropriate to problem

Option 1 Option 2 Option 3
Pros pros 1 pros 2 pros 3
Cons cons 1 cons 2 cons 3

Technical DetailsEdit

Put any equations or analyses tools here; or complicated math.

What to do in DelaysEdit

How much time? fill it function (have a function that does different things depending on how much time is available)

Things to do:

  • Get more data and average it.
  • Zigbee to land (especially for testing)
  • some data might expire? (wind)
  • compute sub-waypoints (wide vs narrow tacks, narrowing tacks, leeway, limit lines, angle of attack)
  • velocity headers

External LinksEdit

Very UsefulEdit

These are links which were GREAT about the topic

Also UsefulEdit

Links that were either not as helpful, or not as on-topic but still related

Community content is available under CC-BY-SA unless otherwise noted.