Wednesday, August 30, 2017

Status snapshot - 30 August 2017

A few more items added to the done list. A couple of enclosure changes tomorrow and it should be good for a power wiring harness... probably a day away from a real test.

Library updates / integration list:


LibraryexternMinimum FunctionsGeneral purpose notes
timestamp.h (DS3231 RTC)
get time, make timestamp...
Done
getRTC() current time>reg[]
setAL1(), setAL2() set alarms from reg[]
setRTC() to update clock
XEEPROM
i2c access to 24LC256 chip
//rem'd out
read(), write() single bytes
readBlock, writeBlock to copy config / comm areas in one call
VMEMDone
read(), write() single bytes, from any memory media
extend to include SDFAT
LogPending
prepare a 16 byte block of log data, either performance or status
solsen.hDone
read(), inits, 
MD_L298D
Both angle/target seeking and basic chip control
Done
getPos(), setDrive(), setTarget() (has az,el angle conversions as well
MCP (MCP 23017)PartialNo defined interface yet
LCDPendingNo defined interface yet
avr (base)PendingGeneric A/D read/write
ESP8266PendingWill need to incorporate
Extend to include SPIFFS comm buffer (eventually)
BattBoxPendingNeed simple avr i2c slave to read some adc lines for current, voltage

// TODO:
  • Write up something that manages the 4 byte structs for describing execution state. Library?Plain array? Library, I think. This is linked to schedule, code and the way it's loaded in memory as objects. Gotta finish that this weekend.
  • copy the sun position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: I forgot the August 31 deadline for autonomous operations. I've started a reverse calendar to count down the work items left. It's about 1 week of time left, and about 6 weeks of work
  • sun sensor - sealing the top and mounting the base to the array.
  • fabric enclosure completion (it's held on with bungee cords right now)
  • user interface 'box' mounting and cable routing, mounting the panels and power switches
  • power and comms cable from the battery box
  • revisit vmem - make it buffer-backed for 32 byte page-writes.

// DONE

  • array mounting and charge cabling
  • platform, table, and mast build, linear actuator tests, azimuth feedback testing and characterization
  • sensor build and testing
  • 3D printing the feedback rack and gear for elevation
  • 3D printing the feedback gear for the XL belt azimuth table
  • 3D printing the sub-panels for the user interface box
  • write up the keywords.txt and example for the XEEPROM library, and test it all out
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.
  • wiring for reset button
  • wiring for keypad
  • cut template for sample control panel
  • mounting tabs for panel  needs do-over
  • switches mounted; wiring diag and harness done
  • drill and mount pcb's to carrier plate

Monday, August 28, 2017

Status snapshot 28 Aug 2017


Library updates / integration list:


A few items added to the done list.

A big to-do is a power supply update to a DC-DC buck which also supports a 3.3V regulator for the ESP-01.



LibraryexternMinimum FunctionsGeneral purpose notes
timestamp.h (DS3231 RTC)
get time, make timestamp...
Done
getRTC() current time>reg[]
setAL1(), setAL2() set alarms from reg[]
setRTC() to update clock
XEEPROM
i2c access to 24LC256 chip
//rem'd out
read(), write() single bytes
readBlock, writeBlock to copy config / comm areas in one call
VMEMDone
read(), write() single bytes, from any memory media
extend to include SDFAT
LogPending
prepare a 16 byte block of log data, either performance or status
solsen.hDone
read(), inits, 
MD_L298D
Both angle/target seeking and basic chip control
Done
getPos(), setDrive(), setTarget() (has az,el angle conversions as well
MCP (MCP 23017)PartialNo defined interface yet
LCDPendingNo defined interface yet
avr (base)PendingGeneric A/D read/write
ESP8266PendingWill need to incorporate
Extend to include SPIFFS comm buffer (eventually)
BattBoxPendingNeed simple avr i2c slave to read some adc lines for current, voltage

// TODO:
  • Write up something that manages the 4 byte structs for describing execution state. Library?Plain array? Library, I think. This is linked to schedule, code and the way it's loaded in memory as objects. Gotta finish that this weekend.
  • copy the sun position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: I forgot the August 31 deadline for autonomous operations. I've started a reverse calendar to count down the work items left. It's about 1 week of time left, and about 6 weeks of work
  • sun sensor - sealing the top and mounting the base to the array.
  • fabric enclosure completion (it's held on with bungee cords right now)
  • user interface 'box' mounting and cable routing, mounting the panels and power switches
  • power and comms cable from the battery box
  • revisit vmem - make it buffer-backed for 32 byte page-writes.

// DONE

  • array mounting and charge cabling
  • platform, table, and mast build, linear actuator tests, azimuth feedback testing and characterization
  • sensor build and testing
  • 3D printing the feedback rack and gear for elevation
  • 3D printing the feedback gear for the XL belt azimuth table
  • 3D printing the sub-panels for the user interface box
  • write up the keywords.txt and example for the XEEPROM library, and test it all out
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.
  • wiring for reset button
  • wiring for keypad
  • cut template for sample control panel

Friday, August 25, 2017

AMS-1117 Voltage Regulator Notes

AMS-1117 (5v version)

Current recommended application:

  • Voltage regulation to ~750mA
  • Max input voltage sources:
    • 4x or 6x AA battery pack (6V - 9V) for 5V systems
    • 3x or 4x AA battery pack for 3.3V systems
    • LiPo 2S battery for 5V systems

Max input voltage:

  • 15V (from the datasheet)
  • 12V as assembled / shipped by the pcb manufacturer
  • 10V from others who have tested the part
Failure input voltage: 13.4V, no-load voltage, as tested from a common 7Ah, 12V SLA battery

Possible failure symptoms:

  • Fail open
  • Fail closed / no regulation
Max output current:

  • 1A (from datasheet)
  • 800mA (from pcb manufacturer)
Power supply using this IC is a common eBay part:


Note the two burn marks on the top of the IC.
This is what it looks like when it's dead.


When I connected power to this board from a 13.4V (12V) lead-acid battery it did NOT survive. Either the current drain was too high; unlikely, as the project was powered from 500mA USB until now, or the voltage was too high. Again, unlikely, as I have 4 batteries and have swapped them around between this and a working project. UPDATE: The other project uses a 3A DC-DC buck converter, not this part. It's likely this part can't be used above 10V (for the 5v output variant).


Failure notes:
I've investigated if there is a dead short somewhere else that isn't back-powered from the USB > FTDI > Adruino Pro Mini, and it doesn't appear so. For the moment I think it's an IC that died on 13.4V input. The eBay listings for these typically list a lower maximum input voltage of 12V, and other tests show a maximum input of 10V.




Thursday, August 24, 2017

MCP23017 Interrupts, Redux.

When testing a library, especially your own, it helps to complete the entire circuit board first. I found that:

1. I didn't run a line from either of the MCP interrupt pins to either of the AVR interrupt pins

2. I didn't connect ANY of the 8 I/O pins on the MCP port B to the header.

After correcting those I still have some pretty odd behaviours, like interrupts being tripped when connecting a wire to a spare ground pin to test the I/O pins. I checked with the data sheet and it confirmed I've set the correct interrupt logic; because I'm using a compare to register it stays tripped until the connection is cleared. I may have to re-think this, because I was expecting the same behavior as interrupt on change, where it wouldn't keep re-tripping.

Also, so I remember, the reason I chose to not swap out my library for the Adafruit library was that I was storing the port reads directly into the register array.

Anyway, I did discover there is still another wiring fault. A cold solder joint or crack or something. I get random interrupts but I can't nail it down to a single pin or connection.

That's what I get for rushing the design and not etching a real PCB.

Wednesday, August 23, 2017

Eclipse 2017

Notes from the recent eclipse:

1. When shooting the sun directly (I used 300mm and a Vari-ND filter) ensure the exposure is low enough to see sunspots - and then double check it. I had the correct exposure but bumped the filter ring and can't see sunspots in the image sequence.

2.  If the eclipse is low enough on the horizon to include 'foreground' like trees, the horizon line etc, shoot wide enough to capture it for interest.

3. There were a few shots online with the ISS and aircraft in front of the sun. Nice.

4. Consider travel for capturing a totality event.

5. Put a color checker card in view for a controlled test.

6. Consider using a motorized slider / controller for a more interesting timelapse. It will need a platform capable of tracking the sun 'perfectly' or require additional software to stabilize...

7. The processing.org sketch for image stabilization of the sun/moon frames is called 'LoadDisplayImages' (it was based on the similarly named example code). It attempts to find the center of the sun but is somewhat fooled by the crescent shape. I decided not to tweak it any further.

Here are links to the videos:




Sunday, August 13, 2017

Atom - platformio = fail

Editing both the main sketch and the libraries was a total hassle in the Arduino IDE. After a quick look around I installed atom and platformio. Very sexy.

UPDATE: platformio is a complete fail. I was getting unusual data from the DS3231 clock, but I couldn't tell if it was my wrapper or the original library that I'd grabbed for the Arduino IDE.

Long story short, I tried renaming the original library folder, installed the first DS3231 library from the platformio gui (after I hunted the gui down) and got the same result.

Ok, no big deal, let's see what the library is doing with the hour/h12/pm data.

Wait, where is the library? It's not in the lib directory. I guess it's global?

So where is the global library folder? It's not visible in the project folder/file list on the left.

I hunt down the library gui button that has the 'reveal in finder' button, and resort to opening the .cpp file in.... TextWrangler. What a waste of time. I can't edit the .cpp file in platformio? I can't select to open it with Atom - platformio just throws a big red error box and pukes.

I'm giving up on platformio for now; it's library system is overly complicated/obtuse/opaque, and I can't easily open my own global library files to edit them at the same as my source code. It is in active development so I can see it getting better, but for now there isn't any difference to just opening everything in TextWrangler and recompiling in the Arduino IDE.

It seems to work; after some futzing around with extra #includes in the projects main .cpp file  I think I foiled the broken library path logic enough - I have a few custom libs and it's compiling without throwing errors because it can't find the Arduino base libs like EEPROM.h and my hacked Wire.h.

It's notion of statically compiled libraries in a per-project /lib folder is totally counterintuitive to why I write libraries in the first place - shared, reusable code. Also, there were a few support questions and the response was 'our libs are better'. Really? Better than what the entire open source community writes? Bullshit.

But whatever, it works for now. Worst case is the author updates it, breaks the logic in a different way, and then I throw it all out and go back to the Arduino IDE, TextWrangler, and forcing recompiles outside by deleting .o files. Blech.


Saturday, August 12, 2017

Status snapshot 11-Aug-17


Library updates / integration list:



LibraryexternMinimum FunctionsGeneral purpose notes
timestamp.h (DS3231 RTC)
get time, make timestamp...
Done
getRTC() current time>reg[]
setAL1(), setAL2() set alarms from reg[]
setRTC() to update clock
XEEPROM
i2c access to 24LC256 chip
//rem'd out
read(), write() single bytes
readBlock, writeBlock to copy config / comm areas in one call
VMEMDone
read(), write() single bytes, from any memory media
extend to include SDFAT
LogPending
prepare a 16 byte block of log data, either performance or status
solsen.hDone
read(), inits, 
MD_L298D
Both angle/target seeking and basic chip control
Done
getPos(), setDrive(), setTarget() (has az,el angle conversions as well
MCP (MCP 23017)PartialNo defined interface yet
LCDPendingNo defined interface yet
avr (base)PendingGeneric A/D read/write
ESP8266PendingWill need to incorporate
Extend to include SPIFFS comm buffer (eventually)
BattBoxPendingNeed simple avr i2c slave to read some adc lines for current, voltage

// TODO:
  • Write up something that manages the 4 byte structs for describing execution state. Library?Plain array? Library, I think. This is linked to schedule, code and the way it's loaded in memory as objects. Gotta finish that this weekend.
  • copy the sun position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: I forgot the August 31 deadline for autonomous operations. I've started a reverse calendar to count down the work items left. It's about 2 weeks of time left, and about 6 weeks of work
  • sun sensor - sealing the top and mounting the base to the array.
  • fabric enclosure completion (it's held on with bungee cords right now)
  • user interface 'box' mounting and cable routing, mounting the panels and power switches
  • power and comms cable from the battery box
  • revisit vmem - make it buffer-backed for 32 byte page-writes.

// DONE

  • array mounting and charge cabling
  • platform, table, and mast build, linear actuator tests, azimuth feedback testing and characterization
  • sensor build and testing
  • 3D printing the feedback rack and gear for elevation
  • 3D printing the feedback gear for the XL belt azimuth table
  • 3D printing the sub-panels for the user interface box
  • write up the keywords.txt and example for the XEEPROM library, and test it all out
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.

Friday, August 11, 2017

Variables and Parameters

The first thing I pulled into the main code was the real time clock / timestamp library, and it turned out to be a good choice because it was non-trivial. Most classes have private and public members, but in the case of 'time', it needs to be accessible to other libraries, like logging and scheduling.

One way is to simply call rtcupdate() to fetch valid entries for a time struct, then add a parameter for it in the function calls. In memory constrained situations this isn't ideal. The stack is only so large and garbage collection is seldom merciful (or timely).

Early on I decided I prefer to create a register array of bytes for my 'globals'. This means I can look down a list of #defines and see which globals I have and how they are organized. It also means that I don't create a lot of near-duplicates (or outright duplicates), pass a lot of useless stuff on the stack, and generally keep things tidy. This is really important on the ATTINY 85 (and 84), but also handy on the 328's. It also means that turning a project into an I2C slave is trivial, since the registers already exist.

The implementation when mixed with several libraries is less obvious. Class files aren't aware of globals; they don't 'see' the uint8_t reg[64] declaration. There are two ways around this; pointers and extern. Both work, but the way I did it, pointers was just ever so slightly clunkier than using extern as I had to pass the address of the global reg[] array in the class .begin() call.

This allows for the following basic rules:


  1. class / private variables: never seen outside the class implementation. Can use get/set syntax for access
  2. class / public variables: never needed outside of either the class or loop(); preferred if no get/set syntax is helpful for housekeeping
  3. shared globals via extern: used to make global scope variables visible to class implementations.
To simplify point 3 even more, the only variable I plan on using this way is the reg[] array. We'll see if that holds up.

UPDATE:

I should probably document how this works... after looking online I see that there is a lot of incomplete examples out there.

main (where setup and loop are):

#include "registers.h"
uint8_t reg[ REG_SIZE ];

void loop() {
  clock.getRTC();
  Serial.print( reg [ DT_MINUTE ] );
  Serial.print( " - ");
  Serial.println( reg [ DT_SECOND ] );

 delay(1000); // for demo, doesn't use RTC for timing
}

registers.h

// fragment only:
#define REG_SIZE 64

#define DT_YEAR   16
#define DT_MONTH  17
#define DT_DATE   18
#define DT_HOUR   19
#define DT_MINUTE 20
#define DT_SECOND 21

Now the library (there is only a reference in the .cpp file, not in the .h):

timestamp.cpp (uses ds3231.h lib for actual i2c comms):

#include "registers.h"
extern uint8_t reg[  ];

void timestamp::getRTC( void ) {
 // fragment
  reg[ DT_MINUTE ] = Clock.getMinute();
  reg[ DT_SECOND ] = Clock.getSecond();
}





Wednesday, August 9, 2017

I decided to kick the can down the road (I mean 'defer'...) the comms buffers into the ESP-8266 code so I can keep moving forward. I don't need buffered comms right now, but doing it via SPIFFS makes more sense (and has more room) than the 32k EEPROM I'm using.

Because I don't need block-write capability (for moving around comm buffers), I also don't need to focus on either the buffer-backed vmem access or on a media-mapped monolithic memory object (instead of one per use).

Or... this...

http://www.cnx-software.com/2017/08/09/microchip-eeram-combines-sram-and-backup-eeprom-into-a-single-chip/





// TODO:

  • Write up something that manages the 4 byte structs for describing execution state. Library?Plain array? Library, I think. This is linked to schedule, code and the way it's loaded in memory as objects. Gotta finish that this weekend.
  • copy the sun position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: I forgot the August 31 deadline for autonomous operations. I've started a reverse calendar to count down the work items left. It's about 2 weeks of time left, and about 6 weeks of work
  • sun sensor - sealing the top and mounting the base to the array.
  • fabric enclosure completion (it's held on with bungee cords right now)
  • user interface 'box' mounting and cable routing, mounting the panels and power switches
  • power and comms cable from the battery box
  • revisit vmem - make it buffer-backed for 32 byte page-writes.

// DONE

  • array mounting and charge cabling
  • platform, table, and mast build, linear actuator tests, azimuth feedback testing and characterization
  • sensor build and testing
  • 3D printing the feedback rack and gear for elevation
  • 3D printing the feedback gear for the XL belt azimuth table
  • 3D printing the sub-panels for the user interface box
  • write up the keywords.txt and example for the XEEPROM library, and test it all out
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.


Tuesday, August 8, 2017

Pulling it together, Part 1 of ?

With all of the major libraries 'done' I thought I'd brainstorm how they would fit together and to see if there were interactions that I'd missed based on who-instantiates-what. After some whiteboarding, this is what it looks like:


Hardware is at far right, in green ink; libraries are in yellow stickies. I re-worked this with blue lines for shared access, and red for exclusive access, and kept simplifying interactions until all the blue was gone. This makes the variable scope clear, and in some cases where expected libraries may not be needed (like DRV).


Monday, August 7, 2017

Another day, another library


I finished the declarations for all of the opcodes and even some of the simpler implementations yesterday. This was a LOT of cut and paste - 128 declarations in total. When I returned to it this morning I started in on the LOG opcode; simply append a timestamped single parameter to the log; in this case the parameter is actually an index into the stringtable, so it could be read back on the LCD screen also.

As I write yet ANOTHER library to represent the logging subsystem it strikes me that I'd much rather be finishing some of the chassis work while the weather is still nice. I have to complete the fabric enclosure around the mast, and the elevation feedback widget needs to get mounted. I also have 85% of the user control panel done, and probably 2-3 weeks to do it.

The other thought rattling around in my head is that without a working comms system, having the flexibility to upload sequence data is a little clunky. So I finish an in-RAM version of the logging library and check back with the to-do list... I think I'll need to change gears for the near-term software solution.

// TODO:

  • Write up something that manages the 4 byte structs for describing execution state. Library?Plain array? Library, I think. This is linked to schedule, code and the way it's loaded in memory as objects. Gotta finish that this weekend.
  • copy the sun position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: I forgot the August 31 deadline for autonomous operations. I've started a reverse calendar to count down the work items left. It's about 2 weeks of time left, and about 6 weeks of work
  • sun sensor - sealing the top and mounting the base to the array.
  • fabric enclosure completion (it's held on with bungee cords right now)
  • user interface 'box' mounting and cable routing, mounting the panels and power switches
  • power and comms cable from the batter box
// DONE
  • array mounting and charg cabling
  • platform, table, and mast build, linear actuator tests, azimuth feedback testing and characterization
  • sensor build and testing
  • 3D printing the feedback rack and gear for elevation
  • 3D printing the feedback gear for the XL belt azimuth table
  • 3D printing the sub-panels for the user interface box
  • write up the keywords.txt and example for the XEEPROM library, and test it all out
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.

Sunday, August 6, 2017

Scheduling, finally

In working on the last bit of implementation for the part of the sched class I noticed a few things:

  • too many 16 bit values for high resolution 
  • high resolution in timing that doesn't matter
  • reliance on inaccurate intervals rather than RTC adjusted time
  • attempt at reuse for both scheduling and logging (as log timestamps)
So I simplified the storage to the following 8 bytes:
  • Year (3 bits) + Month (4 bits) + Flag (1 bit)
  • Date (8 bits)
  • Hour (5 bits) + flags (3 bits)
  • Minutes (4 bits) + flags (2 bits)
  • Interval4 - (8 bits)
    • 4 min resolution
    • max of 1020 minutes (17 hours)
  • IntervalMax (8 bits) - number of recurring events
  • Page (8 bits)
  • Entry (8 bits)
This isn't loaded into SRAM; the Year+Month and Date values are tested (either for a match or for 'any') first. If those match, the event would fire 'today', and the schedule should be loaded.

The flag bits in hour and minute 'start time' aren't specified yet; I have a hunch they will be used to clarify how the interval relates to the start time & recurrence.

Also, rather than counting down, I switched to using the interval and the start time to calculate the next time of day to fire. 'Minutes' are stored in four bits:


0 0
1 4
2 8
3 12
4 16
5 20
6 24
7 28
8 32
9 36
10 40
11 44
12 48
13 52
14 56
15 n/a (maybe 30?)



Saturday, August 5, 2017

Detour, redux.

One library (XEEPROM) turned into two - the second being vmem, a way to wrap read and write of flash, eeprom, xeeprom, or other media. I didn't do it as a stream class (but probably should, later). I also split up addressing so that subsequent reads increment the ADDR position, much like I2C memory access does.

A minor tweak along the way was to change the default page size from 1k to 512bytes; this means that the second pointer has access to individual opcodes without a third offset byte. It does cut the max memory size by half, but the max was already larger than needed for this project, and it means instantiating a few (maybe 8 or more) of these objects saves one byte per object.

Even with two bytes for memory addressing (instead of three) it makes sense to have a 'zero page' style access. I can fake that with a jump table, so instead of JMP (16bit), it would be a JMT (byte), which is an indirect lookup in the table for a real 16 bit address. There is space in the MAP lookup table, so it's an item in the toolkit for later.

Next up is scheduling. Rather than combine schedule info with code info, it's probably easier/safer/cleaner to split the schedule for sequence elements; which becomes 8 bytes. We don't have to load all of this into memory at once, either:

  • Year/Month
  • Date
  • Hour
  • Minute
  • Interval (Lo)
  • Interval (Hi) + Interval (units)
  • Page (of code)
  • Entry (of code)
Interval is a new idea. It won't matter much for a solar array, but it will be handy later. For the sake of exercising the code & idea, I'll use it to for the hourly-ish moves of the panel instead of hard-coding the schedule lookups.

But this brings up something important that wasn't possible with a linear schedule - concurrence. This would normally be the point where the KISS principle should kick in, but it seems worth pursuing. So for now I'll leave it to human operators (and possibly data flags) to catch conflicts.

For now, I have - wait for it - ANOTHER library, SCHED, now half-built, which sits on top of vmem and can read a structure to calculate it's interval and fetch next opcodes and parameters.



// TODO:
  • write up the keywords.txt and example for the XEEPROM library, and test it all out
  • Write up something that manages the 4 byte structs for describing execution state. Library?Plain array? Library, I think. This is linked to schedule, code and the way it's loaded in memory as objects. Gotta finish that this weekend.
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.
  • copy the sun position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: I forgot the August 31 deadline for autonomous operations. I've started a reverse calendar to count down the work items left.

Thursday, August 3, 2017

Detour...

Yesterdays detour: A library for the I2C external EEPROM. I needed a way to wrap the wire() calls to use the page/element/offset, and probably it'll be extended to manage a few other items. At least now I know the 24LC256 chip on the I2C bus works!

This mornings detour was all about the return stack - or lack of return stack. In fleshing out the code I noticed that I hadn't accounted for returning from a SUB. Code in a SUB is like a SEQ, but they are 16 opcodes long because there is no 4 byte schedule header. Also like a SEQ, they aren't read into SRAM in a group, just an opcode at a time.

Whether or not I need a return stack somewhat depends on the wording I've used to describe calling & creating a SUB. In terms of memory it really only has 2 things to describe it; an instruction pointer for the current opcode position, and an A-register for scratch use. SUBs also need to track their caller (the aforementioned missing return stack), because it need not be the running SEQ. The obvious way is to simply strip off the last running record from the execution list, which is the same as a 'return'.

The description of the instruction pointer needs to describe:

  • what memory it's in [two or three bits]
  • what page of that memory [0..255] has it
  • the element of that page [0..31]
  • the opcode number [0..15]
  • any flags (four bits?)
If the A-reg is included in this description, that's four bytes long, so we can store the environment. The only thing we need to add is a master pointer to know which 4-byte record is the 'end'.

In terms of SRAM use, 256 bytes would be 64 calls deep. In the spirit of 'Nobody will ever use 640k of RAM', I think that's plenty. For now.



// TODO:


  • write up the keywords.txt and example for the XEEPROM library, and test it all out
  • Write up something that manages the 4 byte structs for describing execution state. Library?Plain array? Library, I think.
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.
  • copy the sun position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: Forgot the August 31 deadline for autonomous operations. Dang.

Wednesday, August 2, 2017

Keeping It Simple. Stoopid.


Notes from yesterday / today:

I need a running TODO list. Some items are marked  '// TODO' in code comments, but some are related to real-world builds or tweaks. Right now it's in a small notebook I keep with me, but 'out of sight, out of mind' and all that... The list will be at the bottom of every post. Still beats a project plan, but only just.

Looks like the boot procedure needs some work / documentation so I can get a working memory management library done; here is the current setup:

setup()
  • At startup, pull a byte from internal EEPROM with pointers to the rest of config.
    • This is bit-packed, 2 bits per state, 4 states, pointing each SEQ[0..3] to a memory type (flash, internal EEPROM, external EEPROM, FRAM/SD/...)
  • Perform config work by reading in register init-values as needed (bytes 0 to 31) of config.
  • Read in the operating-config to a register array (currently byte 32 to ~96).
  • Addresses for the four prime state sequences (they can be in different memories) are in the MAP structure in that memory. MAP always starts at byte 256, and is 128 bytes long, and each entry is 4 bytes.
  • Validate that SEQ0 memory is reachable, readable, parseable.
  • Prep for loop() with state = POTC (ie, SEQ0) & instruction pointer = 0.
  • Log the end of startup.
loop()
  • Process hardware & flags for state changes (we might go to state = ERROR, for example).
  • Look at the state elements (at boot state = SEQ0); one will have an 'execute now' schedule; 
  • Read-in the opcode and parameter at IP, and dispatch to the interpreter.
  • If the opcode returns zero, then increment the IP (if not, the routine needs more time/loop cycles*; do nothing more.
  • Loop.
*Most opcodes will call functions that complete and return quickly, and are 'blocking'. An obvious exception is rotating the table to a new position, which is non-blocking.

The reason for this extra complexity is to allow different sequences and configurations to be stored in different memories. For example, a skinny version of the daily schedule (SEQ1) is in FLASH, so everything *should* work even if EEPROM gets wiped out. But we might want a much longer sequence for a given day, or if this is used with different hardware (for example, the rover).

// TODO:
  • get the TODO list into the blog
  • organize the reg[ ] array into config and run entries. Those entries that are only used during setup() don't have to be copied in memory. I should be able to save about 32 bytes of SRAM this way.
  • document the current boot sequence (and update the memory map in the spreadsheet)
  • copy the position schedule currently in a FLASH_ARRAY into some of the unused low bytes of internal EEPROM. I think it fits between the reg[] and MAP.
  • document blocking vs non-blocking calls
  • sift thru the current spreadsheet of opcodes and stuff all the blocking calls into one group so we can flag those in the sequence generator - in case we need to run those as 'exclusive'.
  • I had an idea to wrap the stock LCD library so we can include references to a string_table for option-list type fields. Currently it's all numeric. Smells like scope creep.
  • UPDATE: Forgot the August 31 deadline for autonomous operations. Dang.