Sparky v2 – electronics layout

The Version 1 main board of Sparky has a circuit diagram which is neatly broken up into bits, so that every bit does one thing, and they can all be chained together to make up a whole circuit. When we had to add things, it was easy to do, because the diagram was already in bits, so we could swap bits in and out. So, I’m going to try that here. I’ll name each bit for the part, and you should be able to walk through from any part to the end result of that particular bit. Later, I’ll break down the individual bits to their actual wiring, inputs, and outputs. Important parts like capacitors are here so I don’t forget them later, and do not indicate I think a bit is finished.

Power (24 v) -> voltage converter -> 12v and 5v

12v -> smoothing capacitor -> Stepper Driver

12v -> Water pumps (filter and probe, or all in one)

Spark Power -> Spark Board* -> Spark Probe*

Spark Board* -> LVL* -> Arduino

Board cut-outs -> Arduino (input pull-ups)

Frame cut-outs (end stops) -> Arduino

5v Power Indicator LED

Arduino -> Stepper Driver

Reset mini button -> Stepper Driver

Stepper Driver -> Stepper*

* Solved problem/finished item

The spark board sits on a flying lead, and can be put in at any time. The board cut-outs allow us to drive the stepper in the opposite direction to the expected one, by over-riding the rest of the electronics, meaning we can force the probe up or down. The frame cut-outs are safety interlocks, which stop our motor when we are about to go too far, to protect the parts.

So the Arduino will be taking in the LVL pin, and four different cut-outs, and outputting five instruction pins. (Step, Direction, M0, M1, M2). It will also output the Reset pin so we can be sure the stepper driver is following the Arduino and not moving during boot-up, and the sleep pin, so we can control its waking state. The 5V line itself will power the driver itself, so we can’t power it without the LED coming on. I think the main danger to the driver is if we’re running power through the 12v line when we accidentally unplug it, so that might get changed, but for now I’m planning not to power the driver through the Arduino, which might under exceptional circumstances be powered to 5v while the board is off.

ETA: I had a quick convo with Mat and hardly made him wince at all, and I’ve reduced the 24 volt stepper/pump power line to 12 volt, and I’m happier than I was about them being on the same supply. He’s happier than he was because I told him I wasn’t in the same city as him. I was lying, but we do that for people we like. I’m told.

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.

Cooking: Really easy approximately Thai food

Disclaimer: This tastes delicious, but if you have Thai friends, don’t ask for their honest opinion.

1) Put some rice on to steam. If you don’t know how to steam rice, boil it or open a packet or whatever. I don’t care. But the time the rice takes to steam is the outer limits on cooking time. 18 minutes from a cold start.

2) Chop up some garlic. As much as you can be arsed to chop up. Mince it until you’re bored.

3) In a wok, big pan, or whatever you can grab, fry the garlic in some oil. Add as much super-hot Sriracha as you think you can bear, or twice as much green-top Sriracha as necessary. The important thing here is to add some spicy sauce.

4) Add a can of coconut milk. You now have a delicious sauce.

5) Boil everything else in the delicious coconut spicy sauce. You can use a pre-cut stir-fry, or frag some veggies, or throw in leftovers. I won’t judge you. I don’t actually give a fuck what you eat, to be honest, as long as it’s not made of people, and you enjoy it. Lime zest or juice is good, and if you have a G&T habit you’ll have some you need to use up, but fuckit, it’s your decision.

5a) If you’re boiling meat, cut it up small and put it in first, to be sure it’s cooked. If it ends up overcooked, change that next time.

6) Eat. Optionally you can serve it first.

You’re welcome.

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!