WiPy 2.0 and Atom

Yesterday I posted how the WiPy 2.0 and Atom had trouble connecting over IP address and that USB worked great. Well no more. Today for no apparent reason the connection is wonky. Code runs, shows in console, exits and goes to REPL prompt. >> Can’t type in console at that point, reconnect does note reconnect, reset device, code reruns as console show output. Can’t sync, won’t connect……blah 1 hour wasted.

PyCom says they have PyMakr plugin for other editors, cool. Loaded up Sublime, no PyMakr to be found in package list (assuming that’s where it would be but just guessing because PyCom docs are less than accurate.

Next up PyCharm …wait not ready yet according to recent forum post…

I have a brick!

OK, looks like for whatever reason repl>> command line is busted.  Does not work in Atom and or in screen /dev/cu.ser…. mode.

I will have a look some more tomorrow but as far as I can tell – PyCom is not ready for prime time.

PyCom WiPy 2.0

Getting acclimated to the WiPy 2.0 and Expansion Board.  My first “hello world” if you will is to get a TSL2591 Light Sensor running.  It is an i2c device.

Initial Notes on WiPy 2.0 Setup:

  • Datasheet for Expansion Board are difficult to understand.  I assumed that the pinouts would closely resemble that of the WiPy 2.0 but they are not even close.  I am still working with the Expansion Board but dread pulling the WiPy 2.0 off of it and having to rework the circuit
  • ATOM w/Pymkr is flakey at best.  Sync Folder setting not working for me.  I find myself having to restart ATOM after a while as it stops responding often.
  • Firmware Upgrade Fails: I think?  Can’t tell what the latest firmware should be so I am not sure what, if anything happened.
  • Connection with ATOM via IP address never worked.  USB connection is working great.

TSL2991 Code:

Stole this from https://github.com/maxlklaxl/python-tsl2591

Out of the box this code did not work with the WiPy 2.0.  After debugging a bit it turns out the pin outs for SDA and SCL needed to be changed.

Code Snippet (line 52ish of tsl2951.py that I changed to work with WiPy 2.0

[sourcecode language=”python” wraplines=”false” collapse=”false”]
from machine import I2C, Pin
class SMBusEmulator:
__slots__ = (‘i2c’,)
def __init__(self):
self.i2c = I2C(pins=("P8", "P23")) #SDA SCL respectively
[/sourcecode]

Full Code:

[sourcecode language=”python” wraplines=”false” collapse=”false”]
# tsl2591 lux sensor interface
import time

VISIBLE = 2
INFRARED = 1
FULLSPECTRUM = 0

ADDR = 0x29
READBIT = 0x01
COMMAND_BIT = 0xA0
CLEAR_BIT = 0x40
WORD_BIT = 0x20
BLOCK_BIT = 0x10
ENABLE_POWERON = 0x01
ENABLE_POWEROFF = 0x00
ENABLE_AEN = 0x02
ENABLE_AIEN = 0x10
CONTROL_RESET = 0x80
LUX_DF = 408.0
LUX_COEFB = 1.64
LUX_COEFC = 0.59
LUX_COEFD = 0.86

REGISTER_ENABLE = 0x00
REGISTER_CONTROL = 0x01
REGISTER_THRESHHOLDL_LOW = 0x02
REGISTER_THRESHHOLDL_HIGH = 0x03
REGISTER_THRESHHOLDH_LOW = 0x04
REGISTER_THRESHHOLDH_HIGH = 0x05
REGISTER_INTERRUPT = 0x06
REGISTER_CRC = 0x08
REGISTER_ID = 0x0A
REGISTER_CHAN0_LOW = 0x14
REGISTER_CHAN0_HIGH = 0x15
REGISTER_CHAN1_LOW = 0x16
REGISTER_CHAN1_HIGH = 0x17
INTEGRATIONTIME_100MS = 0x00
INTEGRATIONTIME_200MS = 0x01
INTEGRATIONTIME_300MS = 0x02
INTEGRATIONTIME_400MS = 0x03
INTEGRATIONTIME_500MS = 0x04
INTEGRATIONTIME_600MS = 0x05

GAIN_LOW = 0x00
GAIN_MED = 0x10
GAIN_HIGH = 0x20
GAIN_MAX = 0x30

def _bytes_to_int(data):
return data[0] + (data[1]<<8)

from machine import I2C, Pin
class SMBusEmulator:
__slots__ = (‘i2c’,)
def __init__(self):
self.i2c = I2C(pins=("P8", "P23"))

def write_byte_data(self, addr, cmd, val):
buf = bytes([cmd, val])
self.i2c.writeto(addr, buf)

def read_word_data(self, addr, cmd):
assert cmd < 256
buf = bytes([cmd])
self.i2c.writeto(addr, buf)
data = self.i2c.readfrom(addr, 4)
return _bytes_to_int(data)

SENSOR_ADDRESS=0x29

class Tsl2591:
def __init__(
self,
sensor_id,
integration=INTEGRATIONTIME_100MS,
gain=GAIN_LOW
):
print(sensor_id)
self.sensor_id = sensor_id
self.bus = SMBusEmulator()
self.integration_time = integration
self.gain = gain
self.set_timing(self.integration_time)
self.set_gain(self.gain)
self.disable()

def set_timing(self, integration):
self.enable()
self.integration_time = integration
self.bus.write_byte_data(
SENSOR_ADDRESS,
COMMAND_BIT | REGISTER_CONTROL,
self.integration_time | self.gain
)
self.disable()

def set_gain(self, gain):
self.enable()
self.gain = gain
self.bus.write_byte_data(
SENSOR_ADDRESS,
COMMAND_BIT | REGISTER_CONTROL,
self.integration_time | self.gain
)
self.disable()

def calculate_lux(self, full, ir):
if (full == 0xFFFF) | (ir == 0xFFFF):
return 0

case_integ = {
INTEGRATIONTIME_100MS: 100.,
INTEGRATIONTIME_200MS: 200.,
INTEGRATIONTIME_300MS: 300.,
INTEGRATIONTIME_400MS: 400.,
INTEGRATIONTIME_500MS: 500.,
INTEGRATIONTIME_600MS: 600.,
}
if self.integration_time in case_integ.keys():
atime = case_integ[self.integration_time]
else:
atime = 100.

case_gain = {
GAIN_LOW: 1.,
GAIN_MED: 25.,
GAIN_HIGH: 428.,
GAIN_MAX: 9876.,
}

if self.gain in case_gain.keys():
again = case_gain[self.gain]
else:
again = 1.

cpl = (atime * again) / LUX_DF
lux1 = (full – (LUX_COEFB * ir)) / cpl

lux2 = ((LUX_COEFC * full) – (LUX_COEFD * ir)) / cpl

return max([lux1, lux2])

def enable(self):
self.bus.write_byte_data(
SENSOR_ADDRESS,
COMMAND_BIT | REGISTER_ENABLE,
ENABLE_POWERON | ENABLE_AEN | ENABLE_AIEN
)

def disable(self):
self.bus.write_byte_data(
SENSOR_ADDRESS,
COMMAND_BIT | REGISTER_ENABLE,
ENABLE_POWEROFF
)

def get_full_luminosity(self):
self.enable()
time.sleep(0.120*self.integration_time+1)
full = self.bus.read_word_data(
SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN0_LOW
)
ir = self.bus.read_word_data(
SENSOR_ADDRESS, COMMAND_BIT | REGISTER_CHAN1_LOW
)
self.disable()
return full, ir

def get_luminosity(self, channel):
full, ir = self.get_full_luminosity()
if channel == FULLSPECTRUM:
return full
elif channel == INFRARED:
return ir
elif channel == VISIBLE:
return full – ir
else:
return 0

def sample(self):
full, ir = self.get_full_luminosity()
return self.calculate_lux(full, ir)

[/sourcecode]

Simple main.py to print out 10 sensor readings. Hello World Complete!
Will work on posting to the cloud/thingspeak or something of that nature next

[sourcecode language=”python” wraplines=”false” collapse=”false”]
# main.py — put your code here!
import time
from machine import Pin
from machine import I2C
import tsl2591

tsl = tsl2591.Tsl2591(0) # initialize tls2591

cnt = 0

while cnt != 10:
time.sleep(2)
full, ir = tsl.get_full_luminosity() # read raw values (full spectrum and ir spectrum)
lux = tsl.calculate_lux(full, ir) # convert raw values to lux
print(lux, full, ir)
cnt = cnt + 1
[/sourcecode]

Thule Car Top Repair

Plastic and I don’t get along.  Turns out the little plastic “clamps” break pretty easy.  Made some flat aluminum washers of sorts and brought them back to life.

May change how it sits on rails but I am pretty sure it will be below the rail surface.

Sputnik Jig Setup

Experimenting with slotting tubing for dropouts on Sheldon Horizontal Mill.  Vise allows pass through for stays and keeps various diameters centered on slotting saw.  For tapered tubes the vise can be tilted to compensate and a round wire on the top of vee block makes for rigid setup.

Sputnik main tube fixture on the old horizontal mill.

Sputnik Chainstay Fixture on M22 Diamond Mill.

Another view of slotting setup.  Cut a bunch of straight 4130 to dial it in.