Monthly Archives: November 2018

11/17/2018 – Arduino, round 2

Well the Arduino nano performance was atrocious, but I blame that mostly on the Arduino framework itself.  After doing a little bit of research, it seems that reading the analog inputs occurs using a busy wait.  A read can take approximately 100us, so that means that most of the time is spent waiting for the ADC to complete its conversion.  That’s what I will target to make it more efficient.

So in my first rendition of the program, I read four analog inputs and four digital inputs for the inputs of the solenoids.  I could just as easily have read two analog inputs, and six digital inputs to minimize the number of analog reads.  The second program ArduinoBareOPP.ino uses the smaller amount of analog inputs to minimize those reads.

If the Arduino framework forces me to busy wait reading from the analog inputs, it is time to add an interrupt in.  The interrupt gets called after the ADC completes.  At that point, I set the mux to read from the next channel and kick that conversion off.  That means that the conversions are happening in the background without busy waiting for those to complete.  In the interrupt, I also fill currData which holds the value of the inputs.  This is also where I convert it from an ADC sample to a single digital bit using a threshold.

Lastly, I’ve heard that reading bits using digitalRead does a whole bunch of verifications on the inputs.  Why not just read directly from the Atmega328p register and do all the bits at once.  The code at the beginning of “loop” does the necessary bit manipulations to get this to happen using a single read from the PORTC and PORTB registers.  I haven’t converted the output bits to using direct register writes, but they happen so much less frequently, that it won’t make much difference.

So immediately after burning the code, I noticed that the LED which I use to time the loop is much less blinky.  (Before, I could notice a very faint flicker in the LED, but now it seems to be continuously lit dimly.)  That is a good sign.  The real test is when I throw it on the logic analyzer.  So now I get the main loop taking between 23.5 us and 29 us.  That is a significant improvement from the original 488 us.  (1/20th of the time).

So the pulses normally take 4 us, then every once in a while they take 11 us.  This probably means that the interrupt takes about 6.5 us or 7 us.  That also matches up nicely to the 6.5 us difference that I see in the length of time it takes to run the main loop.  It also says that I should take the time to stop using digitalWrite and write directly to the register.

Here is a link to the bare metal version of the code.

11/14/2018 – PSOC vs Arduino nano – Round 1

Finally…today I got my nano boards.  I ordered them on 9/30/2018, and, well 45 days later, I received them.  The main issue that I have is that the seller told me a week after I ordered them that I should expect them within a week.  Seems what he really meant to say is that it would take about another month or more to get them.  Water under the bridge as they say.  (You also get what you pay for, and 5 nanos for only $10.53 isn’t that bad I guess).

So, I soldered the headers on one of the boards, uploaded the program to the board (it uses the old bootloader), and suddenly the little test loop program that could fire solenoids was running.  It was relatively painless except for the fact that the Arduino IDE doesn’t like to program it twice in a row without closing out the program and restarting it.  (It seems to default to looking for the elf file in a location that doesn’t exist).

So I’ve set up the program to act like there are two solenoid wings attached to the board.  A solenoid wing has four inputs, and four MOSFETs for driving a solenoid, so in total there are eight solenoids being polled, and it is controlling eight outputs turning the MOSFETs on and off.  There is enough logic to drive the solenoids for certain period of time for an initial kick and to PWM a single coil flipper.  There is no serial controlling logic to allow a host computer to kick a solenoid, or even read the current state of the inputs from a “rules” computer.  That will come a little later.

At the end of the main loop, I pulse Pin13 (the one attached to the LED) high and then back low to give a quick pulse.  This is a really easy way to do timings to figure out how long it takes to execute the main loop.  After throwing the logic analyzer on Pin13, I got an initial measurement of 488 us.  Hmmm, that is pretty darn slow, especially since I am not doing a lot of the other processing that is necessary to allow a pinball system to work.  Let’s say that the initial pulse is set to 32 ms.  32 ms +/- 488 us has an error of over 1.5%.  I have not tried to “optimize” the program in any way.  There are many websites, that talk about ditching the Arduino framework and bare metal programming the processor.  That will be my next step.  It is an interesting first marker in the sand.

Let’s go over to the PSOC and see how fast it runs its main loop.  I instrumented it up so that bit 4.3 is gives a rising pulse each time the main loop is completed.  (Note:  These timings are with no serial traffic occurring, so there is almost no jitter in the signal).  The PSOC board is configured with the following 4 wings:  neo-pixel, input, solenoid and incandescent.  (The incandescent wing was chosen, because even when idling, it defaults to blinking the incandescent lights so in white wood mode, the lamps can easily be tested)  With that configuration, the main loop occurs every 84.5 us to 86 us, or about 11,500 per second.  The loop rate seems sufficiently high that the error should not affect the power of pop bumpers.  SS3 uses 32 ms for the pop bumpers/slingshots, so 32 ms +/- 86 us or an error of .3%.

As I get more time in the next couple of weeks, I’ll try to bare metal program the Arduino to see if I can get the rate much higher.  Here is a link to the Arduino nano program.

11/3/2018 – Using incandescent wing as HiVolt inputs

Every once in a while, somebody starts emailing me about a technical question and after a couple of emails, a solution is created, and all the information disappears into the ether.  Maybe others could use this information, but I rarely take the time to put the solution out for others to benefit.  Well, since I’m still waiting for my Arduino nano boards, I will take this time to bring up one of those small projects.

A couple months ago a user wrote the following:  “Because of the half scale of my pin, the ball is too light to press a mechanical switch, I use in some instances IR detectors and induction (proximity sensor) switches but induction sensors are 12v (6v to 36v to be precise but I have a 12v psu already).  Is there a simple way to connect it to the processor board without damaging it?”  Originally he proposed using an opto-coupler board as a solution (approx $6.68 for 4 bits + $3 shipping), but suddenly my inherent cheapness caught the better of me.  Could I do it for a much lower cost?

So the basic issue is a 12v input needs to be attached to a processor pin which can only support up to 5v (in the case of the PSOC).  While using an opto-couple board would work wonderfully well, it is just a little too expensive in my opinion for what is needed.  Why not use an incandescent board flipped 180 degrees from how it is normally used?

Could a BS170 transistor make it work?  If the signal goes between 0 and 12V when the IR signal is blocked or not blocked, you could use that as the gate of the transistor.  The drain of the transistor is hooked to the processor input, and the source of the transistor is hooked to the ground of the processor.

Here is a link to the BS170 datasheet:  https://www.onsemi.com/pub/Collateral/BS170-D.PDF

The gate threshold in the On characteristics section of the datasheet says, anything on the gate < 0.8V (the minimum), the transistor is off, so the processor will read high since the input bits are pulled up to 5V internally.  If the gate voltage rises above 3V (the maximum), the transistor will turn on, and the input will be pulled to ground.  BS170 are about 12 cents each if you buy about 100.

The only issue that I can think of off the top of my head is that the sense of the input will be backwards.  Normally a closed switch is read as low.  If it is like an IR sensor, when the sensor is blocked it actually gives low voltage, so that would read high at the processor.  If the IR sensor is not blocked, it gives a high voltage so it would read low at the processor.  If using MPF (Mission Pinball Framework), the input bit can be configured as active high, so it should not be a problem.

On the incandescent wing, the connections that normally attach to the processor go to the gate signals of the BS170s and are attached to the output of the inductor sensor.   Attach the inputs from the processors to what is normally attached to the incandescent bulbs.  (Don’t populate the pullups).  At that point you have 8 of the circuits in a nice little package without having to proto board anything. The gate of a BS170 can handle up to 20V, so your induction sensor at 0-12V should be fine. The BS170 acts as a voltage translator, so that high voltage never touches the processor pins. You will have to tie the logic ground from the processor and the ground of the voltage source for the induction sensor together.

The induction sensor turns on and off the transistor. (turns on and off the switch). The source of the transistor is connected to logic ground. The drain of the transistor is connected to input of the processor. When the inductor sensor sends a high voltage, the transistor or switch closes, so the input is grounded. When the inductor sensor sends a low voltage, the transistor or switch opens, and so the input is floating, but there is an internal pullup resistor in the processor so it reads a high voltage.

Here is an attached picture that he sent me to be a little more clear:

incandescent-to-input-board-12v-to-5v

In other news, I moved the firmware from 0.3.0.1 to 1.0.0.0 after re-running all the regression tests and adding a new test for the CAN_CANCEL.  That feature was added a couple weeks back so that the initial kick of a solenoid could be canceled so things like tap passing is supported by the OPP hardware.  (Thanks to Jan for adding the necessary code in MPF to make that happen on their side).