Arch Flotilla

My Pimoroni Flotilla kit arrived today, and I didn’t have a Raspberry Pi left in workable condition. So, I looked for a set-up that would allow me not to use one. I found a write-up on using Ubuntu and that was hugely useful.

I already had git, so I hit

git clone https://github.com/pimoroni/Flotilla-Daemon-VS.git

in my build area. The daemon is the non-GUI backing that does the hard work of talking to the USB device. It comes without all the dependencies, though. The first one, mentioned in the Ubuntu guide, is libserial. That’s in the AUR. I already had autoconf and libtool. As it happened, I didn’t need to make libserial. This is fortunate, as I found out before I looked in the AUR that pushd was not going to play nicely and I had no idea what that meant.

I also needed libserialport-git from the AUR and websocketpp from the standard repository. I found this out when the makefile borked, and each time there wasn’t a required dependency, I just found it. More than that, I needed to take out the version number in the Makefile. CC = g++-4.9 is probably not allowed because it’s not pure GCC. So, I replaced it with CC = g++ and that worked fine. I swapped OBJECT and LDFLAGS as per the Ubuntu instructions, although I don’t know if that made a difference.

Then I downloaded Rockpool, the interface.

git clone https://github.com/pimoroni/flotilla-offline

That should have run nicely with cd flotilla-offline/rockpool && python rockpool.py but as it happens I have python3 so I made it explicit: python2 rockpool.py and then I was done. Remember to click on Connect rather than waiting politely for the bar to load. You’re acting as a server on the USB connection, so although the address looks like the default, it is and it should be.

Sparky v2 – latest code

The code for Sparky Version 2 is just about finished. I need to swap something I did back-to-front with something Mat did far more elegantly and in fewer lines, but the logic’s sound. Here, with a bit of editing, is Oxygen v7. V1-5 were debugging programs of various sorts.

/* Version 7 of Oxygen is the software implementation.
 * 
 * We do not use pins 0 & 1 (RX/TX) for the main board.
 * We scan LVL after smoothing, compare to the set voltages of 'max_trigger', and 'min_trigger' trigger DIR to 1 or 0 if we want to move.
 * We then hit STEP.
 * Pins should be set to cross directly to DIR and STEP, on veroboard.
 * For convenience, we begin crossing at pin 3, with pin 2 being the zoom toggle
 * 
 * For debugging, we output LVL, MAX, MIN, DIR to serial, and comment that out.
 * 
 * Arduino takes in LVL and four cut-out or direction override pins, plus one 'zoom' pin to speed up or slow down stepping in software, and outputs 7 pins - M0, 1, 2, Step, Dir, /Sleep, /Reset

 */

// hardware constants for board input/output

const int ledPin = 13;
const int zoomPin = 2;  // earth to 0v on Arduino board to increase speed (decrease software delay)

// digital (output) pins (Arduino Pro Mini matched to DRV8825 Stepper Driver)
const int dirPin = 3;
const int stepPin = 4;
const int sleepPin = 5;
const int resetPin = 6;

// step size pin array
int mPins[3] = {7, 8, 9};
const int mPinCount = sizeof(mPins)/sizeof(int);
int mPinStates[mPinCount] = {};
// char *mPinNames[mPinCount] = {"M0", "M1", "M2"};  // Probably only ever in debugging/humanised printing

// Input for cut-outs and manual drive
const int upperCutoutPin = 10;
const int lowerCutoutPin = 11;
const int driveUpPin = 15;  // A1 Can be used as digital pin.
const int driveDownPin = 16;// A2 can be used as digital pin.

// analogue (measurement) pins
const int levelPin = A0;

// measurement constants
/* lvl = 0...1023 (corresponding to 0 to 5v ish) */

const int AnalogReadsPerVolt = 200;  //1000 ish corresponds to 5v

#define volts  // defines volts as a word to ignore by defining it as blank

const int max_trigger = 1 volts * AnalogReadsPerVolt;
const int min_trigger = .1 volts * AnalogReadsPerVolt;

// measurement variables

int lvl = 0;

// move-related variables and calculations

int move_rate = 100;  // Used for speeding up/slowing down in software
int step_ratio = 1;   // Valid options, 1, 2, 4, 8, 16, 32
int step_index = 0;   // used to keep track of which result we want
int stepsize_results[] = {32, 16, 8, 4, 2, 1};
const int stepsize_count = sizeof(stepsize_results) / sizeof(int);
int modePinSettings[stepsize_count] = {5, 4, 3, 2, 1, 0}; // read from High/Low table in docs, M2 first

/* Finds index within modePinSettings, to give us a later result */
int find_index(int array[], int count, int value)
{
  int i;
  for(i=0; i>= 1;
  }
  
  
  digitalWrite(sleepPin, HIGH); // /SLEEP - high to suppress behaviour
  
  // Reset Stepper Board 
  digitalWrite(resetPin, LOW);
  delay(5);
  digitalWrite(resetPin, HIGH); // /RESET
  digitalWrite(ledPin, HIGH);

  //Serial.print("Initialised with min ");
  //Serial.println(min_trigger);
  
}

void loop()  {
  
  
  if(digitalRead(zoomPin) == LOW){  // move rate will appear twice in each loop that moves, once in each loop that does not move
    move_rate = 50;
  } else {
    move_rate = 500;}
  //Serial.print("zoomPin: ");
  //Serial.print(digitalRead(zoomPin));
  //Serial.print("move_rate: ");
  //Serial.println(move_rate);
  
  
  if(digitalRead(driveUpPin) == LOW) {
    //Serial.println("Drive pin: Up.");
    stepUp(move_rate);
  } else if(digitalRead(driveDownPin) == LOW) {
    //Serial.println("Drive pin: Down.");
    stepDown(move_rate); // Behaviour under thick fingers: shout at clumsy person
  } else {  

    lvl = analogRead(levelPin);
    
    if(lvl < min_trigger) {
      //Serial.println("Calling stepUp()");
      stepUp(move_rate);
      // //Serial.println("Moving Up.");  // debugging line
    }
    else if(lvl > max_trigger) {
      //Serial.println("Calling stepDown()");
      stepDown(move_rate);
      // //Serial.println("Moving Down.");  // debugging line
    } else {//Serial.println("Fallthrough.");
    } // lvl not triggering either threshold.  Try earthing it to be sure it goes up.
  }
}

Learn C the Hard Way – inStructions

Mmmm, pun headlines. Not sorry.

So, looking at structs. The write-up for Ex 16 starts with ‘OK, do the write-up’. So, what does the #includes stuff get?

#include <stdio.h> I know about. It lets you put things in and out, so printf lives there.
#include <assert.h> apparently crashes my browser when I search for it. Which is apposite.

Apparently ‘assert’ makes the case that something exists, and then if it doesn’t, throws up a warning to stderr. I guess stderr is also controlled by stdio, as it’s a line to print to. 2/dev/null is my favourite way of stopping the screaming. So in this case it’s checking that who is not NULL. We’re not just picking up a non-entity and trying to work with it, and if who != NULL then I guess that’s the check we’ve just succeeded at what we’ve done.

#include <stdlib.h> gives us malloc() – memory allocation. We’re grabbing a chunk of memory to use for each copy of the struct. So, for obvious reasons, it also gives us free(). Once we’ve allocated, we need to be able to free that up, or our little ghost people will wander in electronic halls forever and there will be a bad Tron sequel.

#include <string.h> must let us play with strings. We have strdup() to handle our name. It also gives us NULL, which is cool, as stlib.h also seems to give that to us. It’s probably very popular at parties.

struct Person defines what a struct called person is. It’s got some attributes inside. So, when we get to struct Person *Person_create we’ve got something to look to and check. It’s sort of like defining an int and then putting a number into it. We define a Thing and then we put how to create the thing as a subsidiary part of that.

struct Person *pointer-to-whatever-our-name-is instantiates a struct and the bits underneath fill it. Note it’s in the middle of our Person_create function. So we grab the attention of the computer, shout at it until it creates a struct with a pointer of the name ‘who’ like Joe or Mat or Cthulhu, and then we go forward from there and allocate memory from that point. For extra points, we choose a bit of memory that isn’t going to write over anything else because you put Cthulhu in the wrong place. (Cthulhu in the wrong place will /severely/ mess up your day.)

The =malloc(sizeof()) part makes sure we’ve allocated memory to the maximum size a Person can be. That’s pretty large in the case of some sedentary sorts.

I think assert(who !=NULL) checks that that happened right, but it might also be that ‘who’ is not a name of 0 characters. Those might look the same in the wrong light. It’s checking who, rather than checking the pointer named who. Someone call for the fucking Tardis.

who->name=stdrup(name) is the stand-out here, so let’s do the next line first.
who->age=age is pretty obvious. Within the struct sub-language, you’ve got -> which says ‘put this into the struct’. So assign ‘name’ from the input of the function into the bit of ‘who’ that is labelled ‘age’.

The same applies with who->name=stdrup(name) except we handle it a bit differently because it’s a string, not an integer. It’s string duplicate. It copies the string we want, the name, into the space we have reserved for the name. I don’t know why that’s explicitly different from int – maybe it’s for security, maybe it’s because it’s easiest to copy a string that way, I just dunno. But that’s what it does.

The return returns the whole object. Later, we’ll see that we run this function with a = in front of it. We’re making ‘who’ and then assigning it to a named pointer we create at the same time.

Person_destroy is my favourite… no, let me alter that. /Running/ Person_destroy is my favourite part of the program. I could sit there running it all day. Only I can’t, because the person has to exist to be destroyed. Again, if there’s a NULL entry, we can’t destroy it, and we output that. I can see a bit more sense in this than in checking the creation. You don’t want to typo the name of a poor unfortunate to be blatted to oblivion, and let them live, after all. But I’m also pretty sure both will be good practice, and if I’m going to have my fun at the end of a function’s life, I can build in sense at the start of it.

We free up the name separately from the rest. I guess because the name is a string, and has to be treated differently, so you only free up to the null byte at the end. Maybe you can group different strings to destr… uh, ‘free’ in the same way as we group everything else on the next line, but we’re doing the strings and then everything else as a one-er.

(Person_destroy($^). Mmmm. It’d be so peaceful.)

Person_print doesn’t check on the existence of the person in question, but I have people for that. It prints out everything we explicitly list, according to the -> syntax. This is likely a bit easier to remember than ***pointer-to_otherPointer(pointer002).

Then we hit main(). It’ll return an int. That int will be 0, because nothing will go wrong. Nothing, you hear me?

Now, we have that equals sign I was talking about up the page. We make a person we label ‘joe’ for the computer. We give him a memory address and fill in all the details, and then we link those details to pointer ‘joe’. He’s 32. His life will be short, although it will have some miraculous aging.

Ditto Frank. Name ‘Frank Blank’, pointer-name, ‘frank’.

%p is the only new-ish part of printf. It gives us the address at which the pointer-thing resides. *joe points to %p where %p is labelled ‘joe’. To find ‘joe’ we look up *joe and that gives us the address %p. Then we run the function that prints out their details, Person_print.

We do the same for Frank. Frank moved away from the neighbourhood and changed his name, but he’s still in his brother Joe’s shadow.

Person_destroy(joe); BAHWHAAWHAHAHAHA…

Ahem, yeah, we just call that function we discussed earlier. Joe’s brief, warm moment of existence is over, and we get back the memory. If we’ve had a /really/ bad moment and killed the wrong person and we know the memory address we might be able to copy him or install a new Joe very percisely over him, but frankly that’s advanced ninja work, and I’ll be having none of it.

Our crime is complete. Nobody can prove Frank or Joe ever existed. We return ‘0’ to say that all is well, and end the main function.

I should go back and write this up as comments in the code, but I had too much fun blorting it into a longer form. Don’wanna!

Probably will, though.

ETA: Did.

Extra credit – can’t work out how to remove memory allocation from stack. I’m not using malloc() so I can’t use free(). Everything else works.

Learn C the Hard Way – reference book

Now that I’ve got a project where I’m using C in the wild, I’m concentrating more on that than on learning. It’s definitely rubbing in the stuff I need to know, but I’m also aware I’m using some very basic tools and there might be better stuff out there. I’m about to approach structs in the book, but so far they haven’t reared their ugly head in anything I need to do. I think.

This is a thing I found with LPythonTHW as well. I took what I needed, and moved on a lot more slowly from that point, but I also went back pretty much constantly to the earlier lessons, to use them for syntax. Every time I’m unsure how to type something, I know that there will be an example somewhere in LCTHW that shows me the thing I’m after. That’s good.

I’ll likely drift away from that model too, unless it turns out it covers things I’m picking up here and there. Stuff like bitshifts are really useful when I’m setting an array of pins and need to go through a binary number in order. I’m sure that’ll come up as an operator, but it hasn’t yet. Having learned how to do it, if I get things wrong there’s still the internet, but for now there’s mostly Zed’s book.

Sparky, redesign in software

So, I’ve probably learned everything I can about electronics from this particular TTL build. For example, I now know what TTL stands for, what 5 volts tastes like, and what a pull-up resistor is. Mat knows that explaining things to a non-expert is haaaaard and that left alone I will do crazy things. So we’ve both learned.

The main board of Sparky is a horror of add-ons, re-mapping, remaking and coloured wires. At least the coloured wires are consistent. Orange for one side of the level we want, green for the other. However, I need to replace most of the bits of the main board with the Arduino.

The step-down needs to be done in hardware. I’m not running 40 volts through an Arduino, even to see what happens[0]. The level comparisons can be done at 5 volts, and indeed it’ll be easier to do that then to twiddle analogue knobs. The first thing we’ll be finding out is whether we’re grounded. If the probe is touching the material, we want to move up. (If we can’t move up, for example because we just hit a switch and the material fell over on the probe, we probably want to cut off the spark circuit, but I’m not building relays into this.)

We want to avoid false positives, so we check a smoothed version of LVL. That smoothing is also done in hardware, with a capacitor.

If the probe isn’t touching the material, then we test to see if the smoothed LVL (see, we’re using the function, or at least a value we passed along) is 0. If so, we move down.

If neither of those things is the case, we leave well alone for Tau, where Tau is the period of the spark capacitor charging. Then we loop again.

‘move’ here is a function, which tells the stepper chip DIR, and then hits the STEP pin. I’m guessing we can do that in two lines of code, and the pause between them will be enough, but DIR might take a moment to wake up, and if that happens it can be dealt with.

So, the shape of it:

LVL +
    |
    +--Check not grounded -- if grounded move up then start loop again.
         |
         + Check not high -- if high, move down then start loop again.
             |
             + If nothing else, stay where you are for Tau then start loop again.

Things I’ll need:

  • LVL measurement – this will expand the timing loop if we end up sampling repeatedly
  • comparator function – /U and /D variables, vs LVL. Check that /U and /D are different and in the correct order – if no space between them, abort and complain.
  • spark delay calculator/outer timing loop
  • movement function
  • tea

On the wishlist:

  • Serial.print output in various formats
  • M0 M1 M2 pins to be isolated with dipswitches. Whatever they are.
  • more tea

[0] If I were going to be doing that, I’d use considerably higher voltage.

Sparky – the state of the code 2015-07-24

Sparky is pretty much functional, and needs making into something good. I’ve re-written the Arduino code with what I’ve learned so far in Learn C the Hard Way, and I’ll use the same board as the Arduino’s on to trigger electronically isolated LEDs, meaning I don’t have to have any outputs, so I can use all the pins for measuring.

The code is as generic as I can make it. Other than the LED pin, none of the pins come pre-named, so you can decide what to plug in where and how, and then output it, as long as you have this program and an Arduino programmer.

/*
 * 
 * Version 6 of Oxygen is an almost complete re-write.
 * V6 mounts the LEDs on the in pins, allowing for easy reading, without needing output.  Physical output can be provided by buffering LEDs to numbered pins.
 * V6 has a timing loop of one second, followed by a toggle of the LED on reserved Pin 13.
 * We do not use pins 0 & 1 (RX/TX).
 * We scan as many lines as we can find pins for, and store them in an array so we can do good things with them.
 * The output to Serial Monitor has two possible outputs of human-readable including pin names, or binary string.
 * 
 * TO DO: binary output function for Serial Monitor
 * TO DO: use millisecond timing from boot-up rather than a set delay to make the timing loop 1 second
 * TO DO: Import oscillator code from V5, as separate function applicable to any pin
 * TO DO: Function to map analogue pins to arbitrary voltage levels (default 5v 2 decimal places).
 * 
 * May^wDoes contain sarcasm.
 */

// unchanging constants and annoying variables

// #include <stdarg.h> - use for more elegant printing later - Mat to show me how.  #includes are not generally needed in Arduino - implicit functions are brought in automatically

// Blink stuff
int ledState = LOW;
int ledPin = 13;


// Pin Arrays that I will later resent treating this way

// digital (measurement) pins

int digitalPinNumbers[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};  // Leave out Pin13.
const int digitalPinCount = sizeof(digitalPinNumbers)/sizeof(int);  // const so we have a non-variable for indexing
char *digitalPinNames[digitalPinCount] = {"Pin 2", "Pin 3", "Pin 4", "Pin 5", "Pin 6", "Pin 7", "Pin 8", "Pin 9", "Pin 10", "Pin 11", "Pin 12"};  // also leave out pin 13
int digitalPinStates[digitalPinCount] = {HIGH}; // Currently working with pull-up resistors.  To be changed.

// analogue (measurement) pins

int analoguePinNumbers[] = {A0, A1, A2, A3, A4, A5}; // A4 & A5 are hard to get to thus likely to float
const int analoguePinCount = sizeof(analoguePinNumbers)/sizeof(int);
char *analoguePinNames[analoguePinCount] = {"Pin A0", "Pin A1", "Pin A2", "Pin A3", "Pin A4", "Pin A5"};
int analoguePinStates[analoguePinCount] = {};


// misplaced functions I will later regret

// !!! TO DO - add binary output !!!

void HumanPrint(){

  Serial.println("Digital Pins");
  for(int i = 0; i < digitalPinCount; i++){
    digitalPinStates[i] = digitalRead(digitalPinNumbers[i]);
    Serial.print(digitalPinNames[i]);
    Serial.print(": ");
    Serial.println(digitalPinStates[i]);
  }
  Serial.println("Analogue Pins");
  for(int i = 0; i < analoguePinCount; i++){
    analoguePinStates[i] = analogRead(analoguePinNumbers[i]);
    Serial.print(analoguePinNames[i]);
    Serial.print(": ");
    Serial.println(analoguePinStates[i]);
  }

}
void setup(){
  Serial.begin(9600);
  
  for(int i = 0; i < digitalPinCount; i++){
    pinMode(digitalPinNumbers[i], INPUT_PULLUP);
  }
  for(int i = 0; i < analoguePinCount; i++){
    pinMode(analoguePinNumbers[i], INPUT);
  }
  pinMode(ledPin, OUTPUT);
  Serial.println("Initialised."); 
}

//Do this later - Mat to demo
//void SerialPrint(char *v0, varargs ...)
//{
//}

void loop() {

  HumanPrint();
  
  ledState = !ledState;
  digitalWrite(ledPin, ledState);
  delay(1000);
}

Learn C the Hard Way – making things useful

Ex 15. Slowed down by altering my system clock and having to stop to deal with that. In fact, the time it took me (no wireless, no wired internet, one small-screened phone) was probably not worth it. I’d have been better off waiting an hour. Modification times are not my friend.

Also not my friend: my brain. I need projects I can use all this new knowledge on. I learn best by doing things and multi-tentacling my brain. That’s like multi-threading, but more muscular, and also rather disgusting. But I need a set of short, easy things that are useful, and that I can do. I’m happier with electronics because I’m working towards a project, but while you can create a project out of logic chips that someone hands you, it’s a lot harder to create a program out of functions that exist. Nobody’s handing me the functions, and choice paralysis is creeping in. It helps that Zed’s adding in independent research and ‘go break this’ and the Extra Credit section – I’m taking those as my projects pro tem, but I’d also really like Stuff To Do. I might look at Arduino projects and what I can do with them. I started learning for Sparky, but once I had that part of the project dealt with, I didn’t have anything else to make the jump between theoretical and ‘wow this is useful’.

So I can probably make the LED array into genuine arrays. I’ll be able to read Mat’s bit of code for the logical read-out to the Serial Monitor, and I can have a minimal physical output plus a proper electronic output. It’ll be a nice break for my brain.

Ooh. Shiny!

Learn C the Hard Way – a lesson where I can’t do too much. Maybe

Ex 8:

This is harder for me to type out with my brain switched off, as it’s new to me so I want to understand it. It’s been pointed out that my wish to understand everything immediately is leading me off down blind alleys. Well, yes. That’s true. I shall try harder not to step off the path, and to trust this book to lead me to where I need to go. I find it hard to stop on the external resea… OK, I find it hard to stop on anything. But I can, so I should. One big risk is that I’ll learn too far ahead and hit a lesson that should be teaching me, and I’ll basically just skim it. I’ve fallen prey to that a lot before. A little learning is a dangerous thing. Although sometimes it can get you cash on game shows, so it’s not all bad.

Extra Credit:

Embedding a null byte in the char name[] increases its size but stops us from reading everything after the null character.

It’s easier to get garbage out of an int than out of a char. I can call for item n+4 out of n in a list of integers and get back what looks like a sensible integer.

If I define an array, I’m defining its size. I can then write out over the end of it, and it stays at the same size (there is a null byte) but I can also pick from it. This gets by the compiler and valgrind. There must be ways of stopping it, presumably tests I can write or flags or some other tool.

Playing with putting characters into ints and ints into characters is… less frustrating than in Python, but probably more dangerous. Python protects me from myself. Here, I can easily put in a character that means something and have it be formatted and it looks right, and it’s just from the wrong place entirely. So I’m pretty damned sure there will be ways of dealing with that. What I need to take from this is that I’ve got the ability to feed X into Y and Y will just chomp it up and not worry about the flavour.

Other stuff:

I’m pretty sure that I will use something like sizeof() in the Arduino, if I want to make an array of my LEDs. Sparky needs visual output. Either that or explicit sizing of the … oh. I think I triggered an error over fitting everything into an explicitly sized array when I tried that last time. I probably didn’t have the null character accounted for. So I could try that next time I’m sitting down to program Sparky. That’ll deal with the error where things are the wrong size, and I can look at why they are really not working instead. Sparky’s next due for a look this evening or on Tuesday.