Brooke's World The life and ramblings of Brooke.

December 21, 2020

Learning about the Pillow Python Library

Filed under: Uncategorized — Brooke @ 11:41 am

Spending some time brushing up on Python.  Spent some time learning about the Pillow 8.0.1 library in Python 3.9.1.

The image I started with.

from PIL import Image
import os

if __name__ == '__main__':
    # Open an image to get some basic info
    infile = "images/numbers-tiger-populations.jpg"
    im = Image.open(infile)
    print(f"""
bits {im.bits}
mode {im.mode}
size {im.size}
    """)

    # Show the image using the local viewer
    input("Press enter when you are ready to see the image.")
    im.show()

    # Create a thumbnail
    size = (128, 128)
    outfile = os.path.splitext(infile)[0] + ".thumbnail"
    with Image.open(infile) as im:
        im.thumbnail(size)
        im.save(outfile, "JPEG")

    # Show the thumbnail
    im = Image.open(outfile)
    input("Press enter when you are ready to see the thumbnail.")
    im.show()

    # convert to grayscale
    im = Image.open(infile).convert('LA')

    # Show the grayscale
    input("Press enter when you are ready to see the grayscale.")
    im.show()

June 8, 2017

SensorBoard v2 final board test section complete

Filed under: Uncategorized — Brooke @ 9:33 pm

I wrote the test sketch for the SN74HC595 and it works.  All sections of the SensorBoard v2 have tested as working.  My next task will be to write some firmware that takes advantage of all 5 sections.  Two temperature sensors, FRAM, photo resistor, and shift register with 8 LEDs.

 

SensorBoard physical design issue

Filed under: Uncategorized — Brooke @ 9:15 pm

Thought I would share a design mistake for the TeensyBreakout w/ SensorBoard v2. It turns out it is a good idea to keep in mind the physical design of your boards when you plan to stack them. I thought I had done pretty well, until I needed to press the reset button! That’s right. It took some creative re-purposing of an ink pen by borrowing its refill to sneak in there and press the button. I am thinking the rev 3 SensorBoard needs to either have a hole that goes through every single “shield” or bring a reset button up to at least the Teensybreakout.

 

June 6, 2017

SensorBoard v2 bringup

Filed under: Uncategorized — Brooke @ 2:05 pm

I tested each of the Arduino sketches with the SensorBoard v2 on a Teensy 3.2 and they all worked. They covered both I2C temp sensors, the SPI FRAM, and the analog-read photoresistor ( values from about 20-1020 ).

The only chip I didn’t have a sketch written for yet was the SN74HC595 shift register. I am working on that sketch next.

May 27, 2017

Testing SN74HC595 shift register with Bus Pirate

Filed under: Uncategorized — Brooke @ 4:54 pm

As part of the CE Header project from the CE Skills course , we have a shift register on the SensorBoard. This chip allows us to light up 8 LEDs ( more with chip chaining ) with 3 pins.  I used a Bus Pirate (Dangerous Prototypes) and probes, from Seeed Studio, to iteratively poke at it until I understood how to talk to it via SPI.

I used a DIP version of the chip in a breadboard and wired it up to the Bus Pirate.  The LEDs are in the breadboard to see it working. Please note, the cable and connectors in the image below are from the Seeed probe cable. Some of the other probe cables have the colors in a different order on the connectors.

I used putty to connect to the Bus Pirate via a mini usb cable.

Note: If you decide to hook this up to an Arduino for testing, using an example sketch, here are the pins to use for your reference:

BP MOSI=pin 11
BP CLK=pin 12
BP CS=pin 8

Command What it does
Initalize the Bus Pirate
M 5 1 1 2 1 2 2
  • Mode SPI
  • Speed 30khz
  • Clock: Idle low *default
  • Output clock edge: Active to idle *default
  • Input sample phase: Middle *default
  • CS: /CS *default, Output Type: Normal (H=3.3V, L=GND)

Make sure the mode number you use is for SPI

W Turn on power, don’t forget this.  If you try to access the FRAM chip before this, you will likely hang the Bus Pirate and have to unplug/plug,setup.

 

Command What it does Output
Turn on output pins
[ 0b00000001 ] Turn on LEDs.  Bit 1 is QA and bit 8 is QH.
QH QG QF QE QD QC QB QA
               
0 0 0 0 0 0 0 1
[ 0b10000000 ] Turn on LEDs
QH QG QF QE QD QC QB QA
               
1 0 0 0 0 0 0 0
[ 0b10101010 ] Turn on LEDs
QH QG QF QE QD QC QB QA
               
1 0 1 0 1 0 1 0
[ 0b00000000 ] Turn all LEDs off
QH QG QF QE QD QC QB QA
               
0 0 0 0 0 0 0 0

 

Looking from the right side

Looking from the left

 

 

Testing MB85RS64V with Bus Pirate

Filed under: Uncategorized — Brooke @ 1:22 pm

As part of the CE Header project from the CE Skills course , I decided to add an IC that used SPI to the SensorBoard. I chose the MB85RS64V chip. This is a Ferroelectric Random Access Memory (FRAM) integrated circuit.  It is similar to FLASH, but with some added benefits. The idea is to be able to write data to it and the data will persist between power off and power on cycles. I used a Bus Pirate (Dangerous Prototypes) and probes, from Seeed Studio, to iteratively poke at it until I understood how to talk to it via SPI.

Once I soldered the MB85RS64V to a small carrier board from Adafruit, I placed it on a breadboard and wired it up to the Bus Pirate. Please note, the cable and connectors in the image below are from the Seeed probe cable. Some of the other probe cables have the colors in a different order on the connectors.

I used putty to connect to the Bus Pirate via a mini usb cable.

Command What it does
Initalize the Bus Pirate
M 5 1 1 2 1 2 2
  • Mode SPI
  • Speed 30khz
  • Clock: Idle low *default
  • Output clock edge: Active to idle *default
  • Input sample phase: Middle *default
  • CS: /CS *default, Output Type: Normal (H=3.3V, L=GND)

Make sure the mode number you use is for SPI

W Turn on power, don’t forget this.  If you try to access the FRAM chip before this, you will likely hang the Bus Pirate and have to unplug/plug,setup.

 

Command What it does Output
Read the ID
[ 0b10011111 r:4 ] Read Chip ID 0x04 0x7F 0x03 0x02

Manufacturer 0x04 Fujitsu
Continuation Code 0x7F ?
Product ID – byte 1
  Proprietary (3 left bits) 0b000 ?
  Density (5 right bits) 0b0011 64kbit
Product ID – byte 2 0x02 2

 

Command What it does Output
Read the status register
[ 0b00000101 r:1 ] Read the register 0x00 (default)

 

Command What it does Output
Read memory
[ 0b00000011 0 0 r:5 ] Read 5 bytes starting at address 0x00 0x00 (msb first) 0x00 0x00 0x00 0x00 0x00

Bytes are initialized to 0 from the manufacturer

[ 0b00000011 0 0 r:8192 ] Read all of the bytes from the chip

 

Write 1 byte to memory
Command What it does Output
[ 0b00000110 ] Write Enable
[ 0b00000010 0x1F 0xFF 0x11 ] Write 5 bytes starting at address 0x1F 0xFF (msb first)  Note: the very last byte is at address 0x1F 0xFF
[ 0b00000100 ] Write Disable
[ 0b00000011 0x1F 0xFF r:1 ] Read the data back from address 0x1F 0xFF 0x11

 

Write 5 bytes to memory
Command What it does Output
[ 0b00000110 ] Write Enable
[ 0b00000010 0x00 0x00 0x01 0x02 0x03 0x04 0x05] Write 5 bytes starting at address 0x00 0x00 (msb first)  Note: the very first byte is at address 0x00 0x00
[ 0b00000100 ] Write Disable
[ 0b00000011 0x00 0x00 r:5 ] Read the data back from address 0x00 0x00 0x01 0x02 0x03 0x04 0x05

 

Go ahead and power off with the w command, unplug the USB from the Bus Pirate, plug it back in.  Go through the set up steps and re-read the data, it should still be there!

It turns out that Adafruit sells this chip ready to go on a breakout board along with an Arduino library!

 

May 9, 2017

MillaMilla_DS7505_Library for Arduino

Filed under: Uncategorized — Brooke @ 7:16 pm

I released my very first Arduino library that can be found right in the Arduino IDE without having to download it and install it manually!  You can still download it and install manually if you like.  It supports the DS7505 temperature sensor.

Many thanks to Adafruit as I started with their MCP9808 library as my template.  I purchase from Adafruit several times a year.  Their products, service, and commitment to education is first class!

To add the library to your project, choose Sketch | Include Library | Manage Libraries … | Search for DS7505

The library supports basic functionality for the DS7505 Temperature Sensor.  Once you install the library, you can open the example sketch and go.

Here’s what the example looks like:

/**************************************************************************/
/*!
This is a demo for the DS7505
----> https://www.maximintegrated.com/en/products/analog/sensors-and-sensor-interface/DS7505.html

This code derived from the Adafruit_MCP9808_Library.

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
*/
/**************************************************************************/

#include <Wire.h>
#include "MillaMilla_DS7505.h"

// Create the DS7505 temperature sensor object
MillaMilla_DS7505 tempsensor = MillaMilla_DS7505();

void setup() {
  delay(2000); // helpful on Teensy debugging to give time to open the serial monitor
  Serial.begin(9600);
  Serial.println("DS7505 demo");
  
  // Make sure the sensor is found, you can also pass in a different i2c
  // address with tempsensor.begin(0x48) for example
  if (!tempsensor.begin()) {
    Serial.println("Couldn't find DS7505!");
    while (1);
  }
}

void loop() {
  //Serial.println("wake up DS7505.... "); // wake up DS7505 for normal power use
  //tempsensor.wake();   // wake up, ready to read!  If you don't wake when shutdown, you still get a temp reading, it will be the last reading while awake.

  //tempsensor.write8(DS7505_REG_CONFIG, DS7505_REG_CONFIG_CONVRESOL_12_BITS); // change default precision from default of 9 bits

  // Read and print out the temperature, then convert to *F
  float c = tempsensor.readTempC();
  float f = c * 9.0 / 5.0 + 32;
  Serial.print("Temp: "); Serial.print(c); Serial.print("*C\t"); 
  Serial.print(f); Serial.println("*F");
  
  //Serial.println("Shutdown DS7505.... ");
  //tempsensor.shutdown(); // shutdown DS7505 for low power
  
  delay(1000);
}

 

If you have a library you would like added to the Arduino IDE, check out the Library Manager FAQ.  It is a very easy to follow reference.  It only took about 2 1/2 days from when I created my issue for it to be found by the IDE.  Thank you to the Library Manager Team!!

November 15, 2016

Salt Reactor : Having a minion ask another minion to execute a module with events and reactors

Filed under: Uncategorized — Brooke @ 3:38 pm

 

I needed to solve the task of having a minion execute a job on another minion and this is how I accomplished the task.  This stemmed from having a minion that runs a web applications which just needed to execute an execution module that already existed, but needed to run on a different minion.

My solution depends on Salt events and reactors to orchestrate the request from the web server minion to the worker minion and have the worker minion give a response of the work it completed back to the web server minion.

Salt version: salt 2016.3.4

Machines:

Host Salt Role Use Case
saltmast16 Salt Master Orchestrator
saltmina16 Salt Minion Where execution module will run
saltminb16 Salt Minion Web server that initiates work

 

 

/srv/salt/_modules/rhtest.py

The event.fire_master call sends the com/millamilla/test/event/finish event to the master

saltminb16

Web Server

 Web Server Files/ Code salmast16

Master

 Master Files/ Code saltmina16

Worker

Worker Files/ Code
Send an event from the web server to the master. Send event
com/millamilla/test/event/start
Python: send_event.py 

import salt.client
import uuid

caller = salt.client.Caller()
event_uuid = str(uuid.uuid1())

caller.sminion.functions['event.send'](
    'com/millamilla/test/event/start',
    {
      'target': "saltmina16",
      'site': "moodle",
      'user': "hedrickbt",
      'uuid': event_uuid,
    }
)
Receive event
com/millamilla/test/event/start
 /etc/salt/master.d/reactor.conf

reactor:
  # ...
  - 'com/millamilla/test/event/start':        
    - salt://reactor/rhtesteventstart.sls   
  # ...
#...
 >>>>>>>>>>>>>>>>>>>>   >>>>>>>>>>>>>>>>>>>>>>>>>>>>
 Master handles event and causes execuction module to run on worker minion Handle com/millamilla/test/event/start Event.  Call execution module on worker.  /srv/salt/reactor/rhtesteventstart.sls

run_it:
  local.rhtest.rhfunc:
    - tgt: {{ data['data']['target'] }}
    - arg:
      - {{ data['data']['site'] }}
      - {{ data['data']['user'] }}
      - {{ data['id'] }}
      - {{ data['data']['uuid'] }}

 

Execute module Created on master:
/srv/salt/_modules/rhtest.py
and sync’d to minions from master via:
salt ‘*’ saltutil.sync_all

import salt

__outputter__ = {
  'rhfunc': 'yaml'
}

def rhfunc(site, user, requesting_host, event_uuid):
  result = {
    "site":site,
    "user":user,
    "requesting_host":requesting_host,
    "uuid":event_uuid
  }

  __salt__['event.fire_master'](
    {
      "site":site,
      "user":user,
      "requesting_host":requesting_host,
      "uuid":event_uuid,
    },
    'com/millamilla/test/event/finish',
  )

  return result
 >>>>>>>>>>>>>>>>>>>  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 After worker minion executes modules send event back to master Receive event
com/millamilla/test/event/finish
/etc/salt/master.d/reactor.conf

reactor:
  # ...
  - 'com/millamilla/test/event/finish':
    - salt://reactor/rhtesteventfinish.sls 
  # ...
<<<<<<<<<<<<<<<<<<< <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 Forward event Master received to the web minion. Receive/Handle Event

com/millamilla/test/event/finish

Python: receive_event.py

This needs to run just after sending the message so it can be listening.  You will want to add code that has a timeout in the for…print loop.  Otherwise, it could run forever.

You will also want to add code to look at the data[‘uuid’] to make sure it is the one you sent out.

Typically, you wouldn’t have a separate send/receive program, but you can.  I plant to create a single script that generates the uuid, sends the request, and waits for a message to return within a timeout period.  If the timeout is exceeded an error would be thrown.

import salt.config
import salt.utils.event
import socket
import os

# Import 3rd-party libs
import salt.ext.six as six

my_hostname = socket.gethostname()

#opts = salt.config.client_config('/etc/salt/minion')
opts = {}
opts['node'] = 'minion'
opts['sock_dir'] = '/var/run/salt'
opts['sock_dir'] = os.path.join(opts['sock_dir'], opts['node'])
opts['id'] = my_hostname
opts['transport'] = 'zeromq'

event = salt.utils.event.get_event(
        opts['node'],
        sock_dir=opts['sock_dir'],
        transport=opts['transport'],
        opts=opts)

for data in event.iter_events(tag='com/millamilla/test/event/finish'):
    print(data)
Handle Event

com/millamilla/test/event/finish

 /srv/salt/reactor/rhtesteventfinish.sls

notify_it:
  local.event.fire:
  - tgt: {{ data['data']['requesting_host'] }}
  - arg:
    - {{ data['data'] }}
    - com/millamilla/test/event/finish
 <<<<<<<<<<<<<<<<<<<  <<<<<<<<<<<<<<<<<<<

October 3, 2013

Using the tymkrs “Turn Me” with an Arduino

Filed under: Uncategorized — Tags: — Brooke @ 11:24 pm

Here is a quick write up on how to use the tymkrs “Turn Me” rotary encoder.  This supports the “push down” feature of the tymkrs kit.

RotaryEncoderDemo_bb     output_window

DSC_0249_for_web

Fritzing Rotary Encoder Part: Rotary Encoder with Knob bth.fzpz

Fritzing Project: RotaryEncoderDemo.fzz

Arduino (1.5) project: RotaryEncoderDemo.ino


 /* Read Quadrature Encoder
  * Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
  * http://playground.arduino.cc/Main/RotaryEncoders
  * Sketch by max wolf / www.meso.net
  * v. 0.1 - very basic functions - mw 20061220
  * Sketch updated by Brooke Hedrick / www.millamilla.com
  * v. 0.2 - Added the "S" pin for encoders with push-down support - bth 09292013
  *        - Put a limit of 255 and 0 in place.  It rolls over automatically at the limits - bth 09292013
  *
  */

 int val;
 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0PinS = 5;
 int encoder0PosUp = 0;
 int encoder0PosDown = 0;
 int encoder0PinALast = LOW;
 int n = LOW;
 int encoder0UpDown = LOW;

 void setup() {
   pinMode(encoder0PinA,INPUT);
   pinMode(encoder0PinB,INPUT);
   pinMode(encoder0PinS,INPUT);
   Serial.begin (9600);
 }

 void loop() {
   encoder0UpDown = digitalRead(encoder0PinS);
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     //Serial.print("up down:");
     //Serial.println(encoder0UpDown);
     if (digitalRead(encoder0PinB) == LOW) {
       if (encoder0UpDown == LOW) {
         encoder0PosUp--;
         if (encoder0PosUp < 0) {
             encoder0PosUp = 255;
         }
       } else {
         encoder0PosDown--;
         if (encoder0PosDown < 0) {
             encoder0PosDown = 255;
         }
       }
     } else {
       if (encoder0UpDown == LOW) {
         encoder0PosUp++;
         if (encoder0PosUp > 255) {
           encoder0PosUp = 0;
         }
       } else {
         encoder0PosDown++;
         if (encoder0PosDown > 255) {
           encoder0PosDown = 0;
         }
       }
     }
     Serial.print(encoder0PosUp);
     Serial.print(" ");
     Serial.println(encoder0PosDown);
   }
   encoder0PinALast = n;
 }

September 28, 2013

Contextual Electronics : Session 1 : Module 3 : Unit 5 : Understanding The Relay Module : Task

Filed under: Uncategorized — Tags: — Brooke @ 12:12 am

Task

  • Create a block diagram for the relay driver circuit.

Module3Unit5_schematic

Git: https://github.com/hedrickbt/ContextualElectronics/tree/Module3Unit5/Session1/MyBenchBuddy/KiCad

Older Posts »

Powered by WordPress