Code made on V1.18 not working on V.1.20
-
Hi All,
I wrote this code over a year or so ago and don't remember too much about it...
Now the devices have been updated/new ones purchased and they are failing on the latest build which I'm a bit confused about. I've tried exploring the documentation but it seems Pycom has had an overhaul of it's documentation and I'm struggling to find what I need so I've come here.
Here is my code:
from LIS2HH12 import LIS2HH12 from pytrack import Pytrack from network import WLAN import machine from machine import Pin from machine import I2C from machine import Timer import socket import binascii import struct import time import array wlan = WLAN(mode=WLAN.STA) nets = wlan.scan() for net in nets: if net.ssid == 'XXX-Pi': print('Network found!') wlan.connect(net.ssid, auth=(net.sec, 'raspberry'), timeout=30) wlan.ifconfig(config=('192.168.1.20', '255.255.255.0', '192.168.1.40', '8.8.8.8')) print(wlan.isconnected()) while not wlan.isconnected(): machine.idle() # save power while waiting print('WLAN connection succeeded!') chrono = Timer.Chrono() chrono.start() HOST = '192.168.1.1' PORT = 10000 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP) print("line 31") print(wlan.isconnected()) sockett = False while sockett == False: try: print('Connection...') s.connect((HOST, PORT)) except OSError: print('xception...') # //machine.reset() else: sockett = True print("line 33") while wlan.isconnected(): lap = chrono.read() py = Pytrack() battery = py.read_battery_voltage() acc = LIS2HH12() xyz = acc.acceleration() x = xyz[0] y = xyz[1] z = xyz[2] b = (x**2 + y**2 + z**2) **(0.5) a = "\n" data = (str(lap) + "," + str(b) + "," + str(battery) + "\n") print(data) s.send(data) print("sent") time.sleep(0.1) if not wlan.isconnected(): machine.reset()
I know it's not perfect but it worked (at the time).
The output is an OSError during line 35: s.connect((HOST, PORT))
Anyone have any ideas what could be going wrong here?
I updated back to V1.18. and it still no longer works...
-
@Dylan as @Gijs wrote, it’s obvious from the output that the module didn’t connect to the WLAN.
What is weird is that even when it works you don’t have the
Network found!
output. Are you running the same code on both?If the first log comes from a device actually running the code you gave, it means it didn’t find the network. Try logging all networks found to check for a typo of some sort, or loop around
scan
(with a small sleep) until you find it.
-
It seems the issue with your 'bricked' device is that it is not actually connected to WiFi (note how it says
line 31 False
. This will cause the socket to throw the exception, as there is no working network adapter available.Your updated device never seems to run through this part:
for net in nets: if net.ssid == 'XXX-Pi': print('Network found!') wlan.connect(net.ssid, auth=(net.sec, 'raspberry'), timeout=30) wlan.ifconfig(config=('192.168.1.20', '255.255.255.0', '192.168.1.40', '8.8.8.8')) print(wlan.isconnected()) while not wlan.isconnected(): machine.idle() # save power while waiting print('WLAN connection succeeded!')
That is supposed to create the connection.
On second thought, perhaps the timeout is too short at 30 ms?
-
Hi, thank you for your reply.
Here are the outputs:
rst:0x7 (TG0WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff8020,len:8 load:0x3fff8028,len:2128 load:0x4009fa00,len:19760 entry 0x400a05bc line 31 False Connection... xception... Connection... xception... Connection... xception...
This is the output from a board that hasn't been updated or touched since I first wrote the code:
Connecting to COM7... WLAN connection succeeded! line 31 True Connection... line 33 0.01096298,0.0,4.696739 sent 0.1555956,1.022109,4.701756 sent 0.2996252,1.023995,4.706775 sent 0.4436324,1.028087,4.701756 sent 0.5876054,1.028255,4.711792 sent 0.7316323,1.027779,4.706775 sent 0.8755957,1.022246,4.696739 sent 1.019628,1.025475,4.701756 sent 1.163599,1.022926,4.701756 sent 1.307628,1.029247,4.706775 sent 1.451632,1.029623,4.696739
When I try to download the code from the older units I only get the main.py file for some reason, I have all the code I wrote though so have been able to re-upload. They are:
import math import time import struct from machine import Pin FULL_SCALE_2G = const(0) FULL_SCALE_4G = const(2) FULL_SCALE_8G = const(3) ODR_POWER_DOWN = const(0) ODR_10_HZ = const(1) ODR_50_HZ = const(2) ODR_100_HZ = const(3) ODR_200_HZ = const(4) ODR_400_HZ = const(5) ODR_800_HZ = const(6) ACC_G_DIV = 1000 * 65536 class LIS2HH12: ACC_I2CADDR = const(30) PRODUCTID_REG = const(0x0F) CTRL1_REG = const(0x20) CTRL2_REG = const(0x21) CTRL3_REG = const(0x22) CTRL4_REG = const(0x23) CTRL5_REG = const(0x24) ACC_X_L_REG = const(0x28) ACC_X_H_REG = const(0x29) ACC_Y_L_REG = const(0x2A) ACC_Y_H_REG = const(0x2B) ACC_Z_L_REG = const(0x2C) ACC_Z_H_REG = const(0x2D) ACT_THS = const(0x1E) ACT_DUR = const(0x1F) def __init__(self, pysense = None, sda = 'P22', scl = 'P21'): if pysense is not None: self.i2c = pysense.i2c else: from machine import I2C self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl)) self.reg = bytearray(1) self.odr = 0 self.full_scale = 0 self.x = 0 self.y = 0 self.z = 0 self.int_pin = None self.act_dur = 0 self.debounced = False self.scales = {FULL_SCALE_2G: 4000, FULL_SCALE_4G: 8000, FULL_SCALE_8G: 16000} self.odrs = [0, 10, 50, 100, 200, 400, 800] whoami = self.i2c.readfrom_mem(ACC_I2CADDR , PRODUCTID_REG, 1) if (whoami[0] != 0x41): raise ValueError("LIS2HH12 not found") # enable acceleration readings at 50Hz self.set_odr(ODR_50_HZ) # change the full-scale to 4g self.set_full_scale(FULL_SCALE_4G) # set the interrupt pin as active low and open drain self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL5_REG, self.reg) self.reg[0] |= 0b00000011 self.i2c.writeto_mem(ACC_I2CADDR , CTRL5_REG, self.reg) # make a first read self.acceleration() def acceleration(self): x = self.i2c.readfrom_mem(ACC_I2CADDR , ACC_X_L_REG, 2) self.x = struct.unpack('<h', x) y = self.i2c.readfrom_mem(ACC_I2CADDR , ACC_Y_L_REG, 2) self.y = struct.unpack('<h', y) z = self.i2c.readfrom_mem(ACC_I2CADDR , ACC_Z_L_REG, 2) self.z = struct.unpack('<h', z) _mult = self.scales[self.full_scale] / ACC_G_DIV return (self.x[0] * _mult, self.y[0] * _mult, self.z[0] * _mult) def roll(self): x,y,z = self.acceleration() rad = math.atan2(-x, z) return (180 / math.pi) * rad def pitch(self): x,y,z = self.acceleration() rad = -math.atan2(y, (math.sqrt(x*x + z*z))) return (180 / math.pi) * rad def set_full_scale(self, scale): self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL4_REG, self.reg) self.reg[0] &= ~0b00110000 self.reg[0] |= (scale & 3) << 4 self.i2c.writeto_mem(ACC_I2CADDR , CTRL4_REG, self.reg) self.full_scale = scale def set_odr(self, odr): self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL1_REG, self.reg) self.reg[0] &= ~0b01110000 self.reg[0] |= (odr & 7) << 4 self.i2c.writeto_mem(ACC_I2CADDR , CTRL1_REG, self.reg) self.odr = odr def enable_activity_interrupt(self, threshold, duration, handler=None): # Threshold is in mg, duration is ms self.act_dur = duration _ths = int((threshold * self.scales[self.full_scale]) / 2000 / 128) & 0x7F _dur = int((duration * self.odrs[self.odr]) / 1000 / 8) self.i2c.writeto_mem(ACC_I2CADDR , ACT_THS, _ths) self.i2c.writeto_mem(ACC_I2CADDR , ACT_DUR, _dur) # enable the activity/inactivity interrupt self.i2c.readfrom_mem_into(ACC_I2CADDR , CTRL3_REG, self.reg) self.reg[0] |= 0b00100000 self.i2c.writeto_mem(ACC_I2CADDR , CTRL3_REG, self.reg) self._user_handler = handler self.int_pin = Pin('P13', mode=Pin.IN) self.int_pin.callback(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=self._int_handler) def activity(self): if not self.debounced: time.sleep_ms(self.act_dur) self.debounced = True if self.int_pin(): return True return False def _int_handler(self, pin_o): if self._user_handler is not None: self._user_handler(pin_o) else: if pin_o(): print('Activity interrupt') else: print('Inactivity interrupt')
import machine from machine import Pin from machine import I2C import time import pycom __version__ = '0.0.1' """ PIC MCU wakeup reason types """ WAKE_REASON_ACCELEROMETER = 1 WAKE_REASON_PUSH_BUTTON = 2 WAKE_REASON_TIMER = 4 WAKE_REASON_INT_PIN = 8 class Pycoproc: """ class for handling interraction with PIC MCU """ I2C_SLAVE_ADDR = const(8) CMD_PEEK = const(0x0) CMD_POKE = const(0x01) CMD_MAGIC = const(0x02) CMD_HW_VER = const(0x10) CMD_FW_VER = const(0x11) CMD_PROD_ID = const(0x12) CMD_SETUP_SLEEP = const(0x20) CMD_GO_SLEEP = const(0x21) CMD_CALIBRATE = const(0x22) CMD_BAUD_CHANGE = const(0x30) CMD_DFU = const(0x31) REG_CMD = const(0) REG_ADDRL = const(1) REG_ADDRH = const(2) REG_AND = const(3) REG_OR = const(4) REG_XOR = const(5) ANSELA_ADDR = const(0x18C) ANSELB_ADDR = const(0x18D) ANSELC_ADDR = const(0x18E) ADCON0_ADDR = const(0x9D) ADCON1_ADDR = const(0x9E) IOCAP_ADDR = const(0x391) IOCAN_ADDR = const(0x392) INTCON_ADDR = const(0x0B) OPTION_REG_ADDR = const(0x95) _ADCON0_CHS_POSN = const(0x02) _ADCON0_ADON_MASK = const(0x01) _ADCON1_ADCS_POSN = const(0x04) _ADCON0_GO_nDONE_MASK = const(0x02) ADRESL_ADDR = const(0x09B) ADRESH_ADDR = const(0x09C) TRISC_ADDR = const(0x08E) PORTA_ADDR = const(0x00C) PORTC_ADDR = const(0x00E) WPUA_ADDR = const(0x20C) WAKE_REASON_ADDR = const(0x064C) MEMORY_BANK_ADDR = const(0x0620) PCON_ADDR = const(0x096) STATUS_ADDR = const(0x083) EXP_RTC_PERIOD = const(7000) def __init__(self, i2c=None, sda='P22', scl='P21'): if i2c is not None: self.i2c = i2c else: self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl)) self.sda = sda self.scl = scl self.clk_cal_factor = 1 self.reg = bytearray(6) self.wake_int = False self.wake_int_pin = False self.wake_int_pin_rising_edge = True try: self.read_fw_version() except Exception: time.sleep_ms(2) try: # init the ADC for the battery measurements self.poke_memory(ANSELC_ADDR, 1 << 2) self.poke_memory(ADCON0_ADDR, (0x06 << _ADCON0_CHS_POSN) | _ADCON0_ADON_MASK) self.poke_memory(ADCON1_ADDR, (0x06 << _ADCON1_ADCS_POSN)) # enable the pull-up on RA3 self.poke_memory(WPUA_ADDR, (1 << 3)) # make RC5 an input self.set_bits_in_memory(TRISC_ADDR, 1 << 5) # set RC6 and RC7 as outputs and enable power to the sensors and the GPS self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 6)) self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 7)) if self.read_fw_version() < 6: raise ValueError('Firmware out of date') except Exception: print(i2c) machine.reset() raise Exception('Board not detected') def _write(self, data, wait=True): self.i2c.writeto(I2C_SLAVE_ADDR, data) if wait: self._wait() def _read(self, size): return self.i2c.readfrom(I2C_SLAVE_ADDR, size + 1)[1:(size + 1)] def _wait(self): count = 0 time.sleep_us(10) while self.i2c.readfrom(I2C_SLAVE_ADDR, 1)[0] != 0xFF: time.sleep_us(100) count += 1 if (count > 500): # timeout after 50ms raise Exception('Board timeout') def _send_cmd(self, cmd): self._write(bytes([cmd])) def read_hw_version(self): self._send_cmd(CMD_HW_VER) d = self._read(2) return (d[1] << 8) + d[0] def read_fw_version(self): self._send_cmd(CMD_FW_VER) d = self._read(2) return (d[1] << 8) + d[0] def read_product_id(self): self._send_cmd(CMD_PROD_ID) d = self._read(2) return (d[1] << 8) + d[0] def peek_memory(self, addr): self._write(bytes([CMD_PEEK, addr & 0xFF, (addr >> 8) & 0xFF])) return self._read(1)[0] def poke_memory(self, addr, value): self._write(bytes([CMD_POKE, addr & 0xFF, (addr >> 8) & 0xFF, value & 0xFF])) def magic_write_read(self, addr, _and=0xFF, _or=0, _xor=0): self._write(bytes([CMD_MAGIC, addr & 0xFF, (addr >> 8) & 0xFF, _and & 0xFF, _or & 0xFF, _xor & 0xFF])) return self._read(1)[0] def toggle_bits_in_memory(self, addr, bits): self.magic_write_read(addr, _xor=bits) def mask_bits_in_memory(self, addr, mask): self.magic_write_read(addr, _and=mask) def set_bits_in_memory(self, addr, bits): self.magic_write_read(addr, _or=bits) def get_wake_reason(self): """ returns the wakeup reason, a value out of constants WAKE_REASON_* """ return self.peek_memory(WAKE_REASON_ADDR) def get_sleep_remaining(self): """ returns the remaining time from sleep, as an interrupt (wakeup source) might have triggered """ c3 = self.peek_memory(WAKE_REASON_ADDR + 3) c2 = self.peek_memory(WAKE_REASON_ADDR + 2) c1 = self.peek_memory(WAKE_REASON_ADDR + 1) time_device_s = (c3 << 16) + (c2 << 8) + c1 # this time is from PIC internal oscilator, so it needs to be adjusted with the calibration value try: self.calibrate_rtc() except Exception: pass time_s = int((time_device_s / self.clk_cal_factor) + 0.5) # 0.5 used for round return time_s def setup_sleep(self, time_s): try: self.calibrate_rtc() except Exception: pass time_s = int((time_s * self.clk_cal_factor) + 0.5) # round to the nearest integer self._write(bytes([CMD_SETUP_SLEEP, time_s & 0xFF, (time_s >> 8) & 0xFF, (time_s >> 16) & 0xFF])) def go_to_sleep(self, gps=True): # enable or disable back-up power to the GPS receiver if gps: self.set_bits_in_memory(PORTC_ADDR, 1 << 7) else: self.mask_bits_in_memory(PORTC_ADDR, ~(1 << 7)) # disable the ADC self.poke_memory(ADCON0_ADDR, 0) if self.wake_int: # Don't touch RA3, RA5 or RC1 so that interrupt wake-up works self.poke_memory(ANSELA_ADDR, ~((1 << 3) | (1 << 5))) self.poke_memory(ANSELC_ADDR, ~((1 << 6) | (1 << 7) | (1 << 1))) else: # disable power to the accelerometer, and don't touch RA3 so that button wake-up works self.poke_memory(ANSELA_ADDR, ~(1 << 3)) self.poke_memory(ANSELC_ADDR, ~(1 << 7)) self.poke_memory(ANSELB_ADDR, 0xFF) # check if INT pin (PIC RC1), should be used for wakeup if self.wake_int_pin: if self.wake_int_pin_rising_edge: self.set_bits_in_memory(OPTION_REG_ADDR, 1 << 6) # rising edge of INT pin else: self.mask_bits_in_memory(OPTION_REG_ADDR, ~(1 << 6)) # falling edge of INT pin self.mask_bits_in_memory(ANSELC_ADDR, ~(1 << 1)) # disable analog function for RC1 pin self.set_bits_in_memory(TRISC_ADDR, 1 << 1) # make RC1 input pin self.mask_bits_in_memory(INTCON_ADDR, ~(1 << 1)) # clear INTF self.set_bits_in_memory(INTCON_ADDR, 1 << 4) # enable interrupt; set INTE) self._write(bytes([CMD_GO_SLEEP]), wait=False) # kill the run pin Pin('P3', mode=Pin.OUT, value=0) def calibrate_rtc(self): # the 1.024 factor is because the PIC LF operates at 31 KHz # WDT has a frequency divider to generate 1 ms # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms # hence the need for the constant self._write(bytes([CMD_CALIBRATE]), wait=False) self.i2c.deinit() Pin('P21', mode=Pin.IN) pulses = pycom.pulses_get('P21', 50) self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl)) try: period = pulses[2][1] - pulses[0][1] except: pass if period > 0: self.clk_cal_factor = (EXP_RTC_PERIOD / period) * (1000 / 1024) def button_pressed(self): button = self.peek_memory(PORTA_ADDR) & (1 << 3) return not button def read_battery_voltage(self): self.set_bits_in_memory(ADCON0_ADDR, _ADCON0_GO_nDONE_MASK) time.sleep_us(50) while self.peek_memory(ADCON0_ADDR) & _ADCON0_GO_nDONE_MASK: time.sleep_us(100) adc_val = (self.peek_memory(ADRESH_ADDR) << 2) + (self.peek_memory(ADRESL_ADDR) >> 6) return (((adc_val * 3.3 * 280) / 1023) / 180) + 0.01 # add 10mV to compensate for the drop in the FET def setup_int_wake_up(self, rising, falling): """ rising is for activity detection, falling for inactivity """ wake_int = False if rising: self.set_bits_in_memory(IOCAP_ADDR, 1 << 5) wake_int = True else: self.mask_bits_in_memory(IOCAP_ADDR, ~(1 << 5)) if falling: self.set_bits_in_memory(IOCAN_ADDR, 1 << 5) wake_int = True else: self.mask_bits_in_memory(IOCAN_ADDR, ~(1 << 5)) self.wake_int = wake_int def setup_int_pin_wake_up(self, rising_edge = True): """ allows wakeup to be made by the INT pin (PIC -RC1) """ self.wake_int_pin = True self.wake_int_pin_rising_edge = rising_edge
from pycoproc import Pycoproc __version__ = '1.4.0' class Pytrack(Pycoproc): def __init__(self, i2c=None, sda='P22', scl='P21'): Pycoproc.__init__(self, i2c, sda, scl)
Wifi network is definitely available, the output of the working device double checks that. The config=('192.168.1.20', get changed per device so that it's not two devices on the same IP, eg 192.168.1.21/22/23.
There is another few sets of these devices out in the field working perfectly, but I fear once/if they are updated they'll all be "bricked" as they have no technical staff.
-
@Dylan can you provide the full output? Is the WiFi network still available, with the same IPs? Is there indeed no other device on the network with that IP? Does the module actually connect to it? Can you ping the module from another device?