From ec6085f7267360b2c9fdc398dadde1c618ca6f65 Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Mon, 20 Jul 2020 22:21:36 +0200 Subject: [PATCH] Initial commit --- abc_measurements.xlsx | Bin 0 -> 11454 bytes .../stepper_nano_zero/.cproject | 122 + .../stepper_nano_zero/.project | 34 + .../stepper_nano_zero/A1333.cpp | 152 + .../stepper_nano_zero/A1333.h | 59 + .../stepper_nano_zero/A4954.cpp | 412 + .../stepper_nano_zero/A4954.h | 90 + .../stepper_nano_zero/A5995.cpp | 337 + .../stepper_nano_zero/A5995.h | 92 + .../stepper_nano_zero/Adafruit_GFX.cpp | 1071 ++ .../stepper_nano_zero/Adafruit_GFX.h | 155 + .../stepper_nano_zero/Adafruit_SSD1306.cpp | 750 + .../stepper_nano_zero/Adafruit_SSD1306.h | 182 + .../stepper_nano_zero/Flash.cpp | 192 + .../stepper_nano_zero/Flash.h | 68 + .../stepper_nano_zero/angle.h | 147 + .../stepper_nano_zero/as5047d.cpp | 322 + .../stepper_nano_zero/as5047d.h | 58 + .../stepper_nano_zero/board.h | 564 + .../stepper_nano_zero/calibration.cpp | 599 + .../stepper_nano_zero/calibration.h | 104 + .../stepper_nano_zero/command.cpp | 381 + .../stepper_nano_zero/command.h | 179 + .../stepper_nano_zero/commands.cpp | 1658 ++ .../stepper_nano_zero/commands.h | 51 + .../stepper_nano_zero/eeprom.cpp | 309 + .../stepper_nano_zero/eeprom.h | 62 + .../stepper_nano_zero/fet_driver.cpp | 1685 ++ .../stepper_nano_zero/fet_driver.h | 124 + .../stepper_nano_zero/ftoa.cpp | 193 + .../stepper_nano_zero/ftoa.h | 48 + .../stepper_nano_zero/gfxfont.h | 24 + .../stepper_nano_zero/glcdfont.c | 276 + .../stepper_nano_zero/nonvolatile.cpp | 145 + .../stepper_nano_zero/nonvolatile.h | 108 + .../stepper_nano_zero/nzs.cpp | 902 + .../stepper_nano_zero/nzs.h | 53 + .../stepper_nano_zero/nzs_lcd.cpp | 600 + .../stepper_nano_zero/nzs_lcd.h | 90 + .../stepper_nano_zero/planner.cpp | 207 + .../stepper_nano_zero/planner.h | 68 + .../stepper_nano_zero/sine.cpp | 198 + .../stepper_nano_zero/sine.h | 43 + .../stepper_nano_zero/stepper_controller.cpp | 1951 +++ .../stepper_nano_zero/stepper_controller.h | 224 + .../stepper_nano_zero/stepper_nano_zero.ino | 13 + ...er_nano_zero.misfittech.samd.nano_zero.bin | Bin 0 -> 119788 bytes ...er_nano_zero.misfittech.samd.nano_zero.elf | Bin 0 -> 917087 bytes .../stepper_nano_zero/steppin.cpp | 314 + .../stepper_nano_zero/steppin.h | 31 + .../stepper_nano_zero/syslog.cpp | 243 + .../stepper_nano_zero/syslog.h | 210 + .../stepper_nano_zero/utils.cpp | 45 + .../stepper_nano_zero/utils.h | 39 + grafana/collectd_InfluxDB Metrics.json | 14085 ++++++++++++++++ grafana/grafana-hangprinter.jpg | Bin 0 -> 3306435 bytes inkscape_drawings/alignment-60-degrees.svg | 259 + inkscape_drawings/alignment-misalignment.svg | 315 + inkscape_drawings/anchor-points.svg | 564 + inkscape_drawings/anchor-positioning.svg | 3555 ++++ inkscape_drawings/bearing-shearoff.svg | 1063 ++ inkscape_drawings/build-volume-collisions.svg | 870 + inkscape_drawings/build-volume.svg | 939 ++ .../coordinate-system-minimized.svg | 436 + inkscape_drawings/coordinate-system.svg | 459 + inkscape_drawings/d-drive-unit.svg | 179 + inkscape_drawings/effector-angles.svg | 2288 +++ .../effector-coordinate-system.svg | 1230 ++ inkscape_drawings/effector-d-offset.svg | 459 + inkscape_drawings/effector-line-angle.svg | 401 + inkscape_drawings/effector-line-guiding.svg | 315 + inkscape_drawings/effector-tool-offsets.svg | 1045 ++ inkscape_drawings/feature-double-lines.svg | 744 + inkscape_drawings/feature-single-lines.svg | 491 + inkscape_drawings/frame-validation.svg | 770 + inkscape_drawings/hangprinter.svg | 853 + inkscape_drawings/line-lengths.svg | 2181 +++ inkscape_drawings/main-drawing.svg | 2610 +++ inkscape_drawings/measuring-XY.svg | 1716 ++ inkscape_drawings/measuring-Z.svg | 1020 ++ inkscape_drawings/pivot-points.svg | 1110 ++ inkscape_drawings/platform.svg | 88 + inkscape_drawings/print diameter.svg | 379 + inkscape_drawings/print volume-shapes.svg | 181 + inkscape_drawings/random-positions.svg | 975 ++ inkscape_drawings/spool-buildup.svg | 718 + inkscape_drawings/spool-line-deflection.svg | 392 + prusaslicer_profile/config.ini | 239 + prusaslicer_profile/trikarus-bed.svg | 661 + 89 files changed, 59574 insertions(+) create mode 100644 abc_measurements.xlsx create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/.cproject create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/.project create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/A1333.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/A1333.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/A4954.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/A4954.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/A5995.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/A5995.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_GFX.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_GFX.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/Flash.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/Flash.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/angle.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/board.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/calibration.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/calibration.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/command.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/command.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/commands.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/commands.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/gfxfont.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/glcdfont.c create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/nzs.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/nzs.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/planner.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/planner.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/sine.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/sine.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/stepper_controller.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/stepper_controller.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.ino create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.misfittech.samd.nano_zero.bin create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.misfittech.samd.nano_zero.elf create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/steppin.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/syslog.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/syslog.h create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/utils.cpp create mode 100644 firmware_smartstepper_trikarus/stepper_nano_zero/utils.h create mode 100644 grafana/collectd_InfluxDB Metrics.json create mode 100644 grafana/grafana-hangprinter.jpg create mode 100644 inkscape_drawings/alignment-60-degrees.svg create mode 100644 inkscape_drawings/alignment-misalignment.svg create mode 100644 inkscape_drawings/anchor-points.svg create mode 100644 inkscape_drawings/anchor-positioning.svg create mode 100644 inkscape_drawings/bearing-shearoff.svg create mode 100644 inkscape_drawings/build-volume-collisions.svg create mode 100644 inkscape_drawings/build-volume.svg create mode 100644 inkscape_drawings/coordinate-system-minimized.svg create mode 100644 inkscape_drawings/coordinate-system.svg create mode 100644 inkscape_drawings/d-drive-unit.svg create mode 100644 inkscape_drawings/effector-angles.svg create mode 100644 inkscape_drawings/effector-coordinate-system.svg create mode 100644 inkscape_drawings/effector-d-offset.svg create mode 100644 inkscape_drawings/effector-line-angle.svg create mode 100644 inkscape_drawings/effector-line-guiding.svg create mode 100644 inkscape_drawings/effector-tool-offsets.svg create mode 100644 inkscape_drawings/feature-double-lines.svg create mode 100644 inkscape_drawings/feature-single-lines.svg create mode 100644 inkscape_drawings/frame-validation.svg create mode 100644 inkscape_drawings/hangprinter.svg create mode 100644 inkscape_drawings/line-lengths.svg create mode 100644 inkscape_drawings/main-drawing.svg create mode 100644 inkscape_drawings/measuring-XY.svg create mode 100644 inkscape_drawings/measuring-Z.svg create mode 100644 inkscape_drawings/pivot-points.svg create mode 100644 inkscape_drawings/platform.svg create mode 100644 inkscape_drawings/print diameter.svg create mode 100644 inkscape_drawings/print volume-shapes.svg create mode 100644 inkscape_drawings/random-positions.svg create mode 100644 inkscape_drawings/spool-buildup.svg create mode 100644 inkscape_drawings/spool-line-deflection.svg create mode 100644 prusaslicer_profile/config.ini create mode 100644 prusaslicer_profile/trikarus-bed.svg diff --git a/abc_measurements.xlsx b/abc_measurements.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d6bb93adf9a2436722d314cc55997024bc9c3e8a GIT binary patch literal 11454 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 literal 0 HcmV?d00001 diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/.cproject b/firmware_smartstepper_trikarus/stepper_nano_zero/.cproject new file mode 100644 index 0000000..114531f --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/.cproject @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/.project b/firmware_smartstepper_trikarus/stepper_nano_zero/.project new file mode 100644 index 0000000..41a61b6 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/.project @@ -0,0 +1,34 @@ + + + NZS + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + arduino + 2 + C:/Users/tramp_000/AppData/Local/Arduino15/packages/arduino/hardware/samd/1.6.8/cores/arduino + + + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.cpp new file mode 100644 index 0000000..168493d --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.cpp @@ -0,0 +1,152 @@ +/********************************************************************** + Copyright (C) 2019 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include +#include "syslog.h" +#include "A1333.h" +#include "SPI.h" +#include +#include "board.h" + + +#define A1333_CMD_NOP (0x0000) +#define A1333_ANG15 (0x3200) + +SPISettings settingsA(500000, MSBFIRST, SPI_MODE3); ///400000, MSBFIRST, SPI_MODE1); + +boolean A1333::begin(int csPin) +{ + + digitalWrite(PIN_AS5047D_CS,LOW); //pull CS LOW by default (chip powered off) + digitalWrite(PIN_MOSI,LOW); + digitalWrite(PIN_SCK,LOW); + digitalWrite(PIN_MISO,LOW); + pinMode(PIN_MISO,OUTPUT); + delay(1000); + + + digitalWrite(PIN_AS5047D_CS,HIGH); //pull CS high + + pinMode(PIN_MISO,INPUT); + + + chipSelectPin=csPin; + + LOG("csPin is %d",csPin); + pinMode(chipSelectPin,OUTPUT); + digitalWrite(chipSelectPin,HIGH); //pull CS high by default + delay(1); + + SPI.begin(); //AS5047D SPI uses mode=1 (CPOL=0, CPHA=1) + + LOG("Begin A1333..."); + + LOG("Address is 0x%04X",readAddress(A1333_ANG15)); +} + + +//read the encoders +int16_t A1333::readAddress(uint16_t addr) +{ + uint16_t data; + //make sure it is a write by setting bit 14 + //addr=addr | 0x4000; + + SPI.beginTransaction(settingsA); + digitalWrite(chipSelectPin, LOW); + delayMicroseconds(1); + //clock out the address to read + //LOG("address 0x%04X",addr); + SPI.transfer16(addr); + digitalWrite(chipSelectPin, HIGH); + delayMicroseconds(1); + digitalWrite(chipSelectPin, LOW); + //clock out zeros to read in the data from address + data=SPI.transfer16(0x00); + + digitalWrite(chipSelectPin, HIGH); + SPI.endTransaction(); + + return data; +} + +//read the encoders +int16_t A1333::readEncoderAngle(void) +{ + + return readAddress(A1333_ANG15)>>1; +} + +int16_t A1333::readEncoderAnglePipeLineRead(void) +{ + static bool first=true; + uint16_t addr = A1333_ANG15; + uint16_t addr2; + uint16_t data; + + if (first) + { + //make sure it is a write by setting bit 14 + //addr2=addr | 0x4000; + SPI.beginTransaction(settingsA); + digitalWrite(chipSelectPin, LOW); + delayMicroseconds(1); + //clock out the address to read + SPI.transfer16(addr); + digitalWrite(chipSelectPin, HIGH); + delayMicroseconds(1); + digitalWrite(chipSelectPin, LOW); + delayMicroseconds(1); + //clock out zeros to read in the data from address + data=SPI.transfer16(addr); + + digitalWrite(chipSelectPin, HIGH); + SPI.endTransaction(); + first=false; + return data>>1; + } + + SPI.beginTransaction(settingsA); + digitalWrite(chipSelectPin, LOW); + delayMicroseconds(1); + //clock out zeros to read in the data from address + data=SPI.transfer16(addr); + + digitalWrite(chipSelectPin, HIGH); + SPI.endTransaction(); + return data>>1; +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.h b/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.h new file mode 100644 index 0000000..ee9ee68 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.h @@ -0,0 +1,59 @@ +/********************************************************************** + Copyright (C) 2019 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef A1333_H_ +#define A1333_H_ + +#include + +#define A1333_DEGREES_PER_BIT (360.0/(float)(0x7FFF)) + +class A1333 { + private: + int chipSelectPin; + public: + boolean begin(int csPin); + int16_t readEncoderAngle(void); + int16_t readAddress(uint16_t addr); + int16_t readEncoderAnglePipeLineRead(void); + void diagnostics(char *ptrStr) {return;}; + bool getError(void) {return false;}; +}; + + + +#endif /* A1333_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.cpp new file mode 100644 index 0000000..61388a4 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.cpp @@ -0,0 +1,412 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "A4954.h" +#include "wiring_private.h" +#include "syslog.h" +#include "angle.h" +#include "Arduino.h" +#include "sine.h" + +static uint8_t pinState=0; + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + + + + +#define DAC_MAX (0x01FFL) +// Wait for synchronization of registers between the clock domains +static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused)); +static void syncTCC(Tcc* TCCx) { + //int32_t t0=1000; + while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK) + { + // t0--; + // if (t0==0) + // { + // break; + // } + // delay(1); + } +} + + +static inline void bridge1(int state) +{ + if (state==0) + { + PORT->Group[g_APinDescription[PIN_A4954_IN1].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN1].ulPin].bit.PMUXEN = 0; + GPIO_OUTPUT(PIN_A4954_IN1);//pinMode(PIN_A4954_IN1,OUTPUT); + GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT); + GPIO_HIGH(PIN_A4954_IN1);// digitalWrite(PIN_A4954_IN1, HIGH); + GPIO_LOW(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, LOW); + //pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT); + pinState=(pinState & 0x0C) | 0x1; + } + if (state==1) + { + PORT->Group[g_APinDescription[PIN_A4954_IN2].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN2].ulPin].bit.PMUXEN = 0; + GPIO_OUTPUT(PIN_A4954_IN2);//pinMode(PIN_A4954_IN2,OUTPUT); + GPIO_OUTPUT(PIN_A4954_IN1);pinMode(PIN_A4954_IN1,OUTPUT); + GPIO_LOW(PIN_A4954_IN1);//digitalWrite(PIN_A4954_IN1, LOW); + GPIO_HIGH(PIN_A4954_IN2);//digitalWrite(PIN_A4954_IN2, HIGH); + //pinPeripheral(PIN_A4954_IN1, PIO_TIMER); + pinState=(pinState & 0x0C) | 0x2; + } + if (state==3) + { + GPIO_LOW(PIN_A4954_IN1); + GPIO_LOW(PIN_A4954_IN2); + //digitalWrite(PIN_A4954_IN1, LOW); + //digitalWrite(PIN_A4954_IN2, LOW); + } +} + +static inline void bridge2(int state) +{ + if (state==0) + { + PORT->Group[g_APinDescription[PIN_A4954_IN3].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN3].ulPin].bit.PMUXEN = 0; + GPIO_OUTPUT(PIN_A4954_IN3); //pinMode(PIN_A4954_IN3,OUTPUT); + GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT); + GPIO_HIGH(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, HIGH); + GPIO_LOW(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, LOW); + //pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT); + pinState=(pinState & 0x03) | 0x4; + } + if (state==1) + { + PORT->Group[g_APinDescription[PIN_A4954_IN4].ulPort].PINCFG[g_APinDescription[PIN_A4954_IN4].ulPin].bit.PMUXEN = 0; + GPIO_OUTPUT(PIN_A4954_IN4);//pinMode(PIN_A4954_IN4,OUTPUT); + GPIO_OUTPUT(PIN_A4954_IN3);//pinMode(PIN_A4954_IN3,OUTPUT); + GPIO_LOW(PIN_A4954_IN3);//digitalWrite(PIN_A4954_IN3, LOW); + GPIO_HIGH(PIN_A4954_IN4);//digitalWrite(PIN_A4954_IN4, HIGH); + //pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT); + pinState=(pinState & 0x03) | 0x8; + } + if (state==3) + { + GPIO_LOW(PIN_A4954_IN3); + GPIO_LOW(PIN_A4954_IN4); + //digitalWrite(PIN_A4954_IN3, LOW); + //digitalWrite(PIN_A4954_IN4, LOW); + } +} + +static void enableTCC0(uint8_t percent) +{ +#ifdef MECHADUINO_HARDWARE + return; +#else + Tcc* TCCx = TCC0 ; + + + uint32_t ulValue=((uint32_t)(100-percent)*480)/100; + //ERROR("Enable TCC0"); + + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; + + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + + //ERROR("Setting TCC %d %d",ulValue,ulPin); + TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + syncTCC(TCCx); + + // Set TCx as normal PWM + TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; + syncTCC(TCCx); + + // Set TCx in waveform mode Normal PWM + TCCx->CC[1].reg = (uint32_t)ulValue; //ch5 //IN3 + syncTCC(TCCx); + + TCCx->CC[2].reg = (uint32_t)ulValue; //ch6 //IN4 + syncTCC(TCCx); + + TCCx->CC[3].reg = (uint32_t)ulValue; //ch7 //IN2 + syncTCC(TCCx); + + TCCx->CC[1].reg = (uint32_t)ulValue; //ch1 == ch5 //IN1 + + syncTCC(TCCx); + + // Set PER to maximum counter value (resolution : 0xFF) + TCCx->PER.reg = DAC_MAX; + syncTCC(TCCx); + + // Enable TCCx + TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; + syncTCC(TCCx); + //ERROR("Enable TCC0 DONE"); +#endif +} + +static void setDAC(uint32_t DAC1, uint32_t DAC2) +{ + TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF12 + syncTCC(TCC1); + TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF34 + syncTCC(TCC1); + + +} + +static void setupDAC(void) +{ + Tcc* TCCx = TCC1 ; + + + pinPeripheral(PIN_A4954_VREF34, PIO_TIMER_ALT); + pinPeripheral(PIN_A4954_VREF12, PIO_TIMER); + + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; + + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + + //ERROR("Setting TCC %d %d",ulValue,ulPin); + TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + syncTCC(TCCx); + + // Set TCx as normal PWM + TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; + syncTCC(TCCx); + + // Set TCx in waveform mode Normal PWM + TCCx->CC[1].reg = (uint32_t)0; + syncTCC(TCCx); + + TCCx->CC[0].reg = (uint32_t)0; + syncTCC(TCCx); + + // Set PER to maximum counter value (resolution : 0xFFF = 12 bits) + // =48e6/2^12=11kHz frequency + TCCx->PER.reg = DAC_MAX; + syncTCC(TCCx); + + // Enable TCCx + TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; + syncTCC(TCCx); + +} + + +void A4954::begin() +{ + //setup the A4954 pins + digitalWrite(PIN_A4954_IN3,LOW); + pinMode(PIN_A4954_IN3,OUTPUT); + digitalWrite(PIN_A4954_IN4,LOW); + pinMode(PIN_A4954_IN4,OUTPUT); + digitalWrite(PIN_A4954_IN2,LOW); + pinMode(PIN_A4954_IN2,OUTPUT); + digitalWrite(PIN_A4954_IN1,LOW); + pinMode(PIN_A4954_IN1,OUTPUT); + + //setup the PWM for current on the A4954, set for low current + digitalWrite(PIN_A4954_VREF12,LOW); + digitalWrite(PIN_A4954_VREF34,LOW); + pinMode(PIN_A4954_VREF34, OUTPUT); + pinMode(PIN_A4954_VREF12, OUTPUT); + + enabled=true; + lastStepMicros=0; + forwardRotation=true; + + enableTCC0(90); + setupDAC(); +// +// int i=0; +// bridge1(0); +// bridge2(0); +//while (1) +// { +// int32_t x; +// WARNING("MA %d",i); +// x=(int32_t)((int64_t)i*(DAC_MAX))/3300; +// setDAC(x,x); +// delay(1000); +// i=i+10; +// if (i>1000) +// { +// i=0; +// } +// +// } + +// +// WARNING("Setting DAC for 500mA output"); +// setDAC((int32_t)((int64_t)1000*(DAC_MAX))/3300,(int32_t)((int64_t)1000*(DAC_MAX))/3300); +// bridge1(0); +// bridge2(0); +// while(1) +// { +// +// } + return; +} + +void A4954::limitCurrent(uint8_t percent) +{ +#ifdef MECHADUINO_HARDWARE + return; +#else + //WARNING("current limit %d",percent); + enableTCC0(percent); + if (pinState & 0x01) + { + pinPeripheral(PIN_A4954_IN2, PIO_TIMER_ALT); //TCC0 WO[7] + } + if (pinState & 0x02) + { + pinPeripheral(PIN_A4954_IN1, PIO_TIMER); //TCC0 WO[1] + } + if (pinState & 0x04) + { + pinPeripheral(PIN_A4954_IN4, PIO_TIMER_ALT); + } + if (pinState & 0x08) + { + pinPeripheral(PIN_A4954_IN3, PIO_TIMER_ALT); + } +#endif +} + + +void A4954::enable(bool enable) +{ + enabled=enable; + if (enabled == false) + { + WARNING("A4954 disabled"); + setDAC(0,0); //turn current off + bridge1(3); //tri state bridge outputs + bridge2(3); //tri state bridge outputs + } +} + + + +//this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step. +// stepAngle is in A4954_NUM_MICROSTEPS units.. +// The A4954 has no idea where the motor is, so the calling function has to +// to tell the A4954 what phase to drive motor coils. +// A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees +// Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you +// currently are. +int32_t A4954::move(int32_t stepAngle, uint32_t mA) +{ + uint16_t angle; + int32_t cos,sin; + int32_t dacSin,dacCos; + //static int i=0; + + if (enabled == false) + { + //WARNING("A4954 disabled"); + setDAC(0,0); //turn current off + bridge1(3); //tri state bridge outputs + bridge2(3); //tri state bridge outputs + return stepAngle; + } + + //WARNING("move %d %d",stepAngle,mA); + //handle roll overs, could do with modulo operator + stepAngle=stepAngle%SINE_STEPS; + + //figure out our sine Angle + // note our SINE_STEPS is 4x of microsteps for a reason + //angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS; + angle=(stepAngle); + + //calculate the sine and cosine of our angle + sin=sine(angle); + cos=cosine(angle); + + //if we are reverse swap the sign of one of the angels + if (false == forwardRotation) + { + cos=-cos; + } + + //scale sine result by current(mA) + dacSin=((int32_t)mA*(int64_t)abs(sin))/SINE_MAX; + + //scale cosine result by current(mA) + dacCos=((int32_t)mA*(int64_t)abs(cos))/SINE_MAX; + +// if (i==0) +// { +// WARNING("dacs are %d %d",dacSin,dacCos); +// } + + //convert value into DAC scaled to 3300mA max + dacCos=(int32_t)((int64_t)dacCos*(DAC_MAX))/3300; + //convert value into DAC scaled to 3300mA max + dacSin=(int32_t)((int64_t)dacSin*(DAC_MAX))/3300; + + //WARNING("dacs are %d %d ",dacSin,dacCos); + + setDAC(dacSin,dacCos); + + if (sin>0) + { + bridge1(1); + }else + { + bridge1(0); + } + if (cos>0) + { + bridge2(1); + }else + { + bridge2(0); + } + +// if (i++>3000) +// { +// i=0; +// } + // YELLOW_LED(led); + // led=(led+1) & 0x01; + lastStepMicros=micros(); + return stepAngle; +} +#pragma GCC pop_options + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.h b/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.h new file mode 100644 index 0000000..c66decb --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.h @@ -0,0 +1,90 @@ +/********************************************************************** + Copyright (C) 2019 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __A4954__H__ +#define __A4954__H__ +#include +#include "board.h" +#include "angle.h" +#include "sine.h" + +#define A4954_NUM_MICROSTEPS (256) +#define A4954_MIN_TIME_BETWEEN_STEPS_MICROS (1000) + +//prevent someone for making a mistake with the code +#if ((A4954_NUM_MICROSTEPS*4) != SINE_STEPS) +#error "SINE_STEPS must be 4x of Micro steps for the move function" +#endif + + + +/* + * When it comes to the stepper driver if we use angles + * we will always have a rounding error. For example + * a 0-65536(360) angle for 1.8 degree step is 327.68 so + * if you increment 200 of these as 327 you have a 13.6 error + * after one rotation. + * If you use floating point the effect is the same but takes longer. + * + * The only error-less accumulation system is to use native units, ie full + * steps and microsteps. + * + */ + +class A4954 +{ +private: + uint32_t lastStepMicros; // time in microseconds that last step happened + bool forwardRotation=true; + volatile bool enabled=true; + +public: + void begin(void); + + //moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step. + int32_t move(int32_t stepAngle, uint32_t mA); + + uint32_t microsSinceStep(void) {return micros()-lastStepMicros;}; + void setRotationDirection(bool forward) {forwardRotation=forward;}; + + void enable(bool enable); + void limitCurrent(uint8_t percent); //higher more current +}; + + + +#endif //__A4954__H__ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.cpp new file mode 100644 index 0000000..f2b8a9f --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.cpp @@ -0,0 +1,337 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + + +#include "A5995.h" +#include "wiring_private.h" +#include "syslog.h" +#include "angle.h" +#include "Arduino.h" +#include "sine.h" + +static uint8_t pinState=0; + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + + + + +#define DAC_MAX (0x01FFL) +// Wait for synchronization of registers between the clock domains +static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused)); +static void syncTCC(Tcc* TCCx) { + //int32_t t0=1000; + while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK) + { + // t0--; + // if (t0==0) + // { + // break; + // } + // delay(1); + } +} + + + +static void setDAC(uint32_t DAC1, uint32_t DAC2) +{ + TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF2 + syncTCC(TCC1); + TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF1 + syncTCC(TCC1); + +} + +static void setupDAC(void) +{ + Tcc* TCCx = TCC1 ; + + + pinPeripheral(PIN_A5995_VREF1, PIO_TIMER_ALT); + pinPeripheral(PIN_A5995_VREF2, PIO_TIMER); + + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; + + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + + //ERROR("Setting TCC %d %d",ulValue,ulPin); + TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + syncTCC(TCCx); + + // Set TCx as normal PWM + TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; + syncTCC(TCCx); + + // Set TCx in waveform mode Normal PWM + TCCx->CC[1].reg = (uint32_t)0; + syncTCC(TCCx); + + TCCx->CC[0].reg = (uint32_t)0; + syncTCC(TCCx); + + // Set PER to maximum counter value (resolution : 0xFFF = 12 bits) + // =48e6/2^12=11kHz frequency + TCCx->PER.reg = DAC_MAX; + syncTCC(TCCx); + + // Enable TCCx + TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; + syncTCC(TCCx); + +} + + +void A5995::begin() +{ + //setup the A5995 pins + digitalWrite(PIN_A5995_ENABLE1,LOW); + pinMode(PIN_A5995_ENABLE1,OUTPUT); + digitalWrite(PIN_A5995_ENABLE2,LOW); + pinMode(PIN_A5995_ENABLE2,OUTPUT); + digitalWrite(PIN_A5995_MODE1,LOW); + pinMode(PIN_A5995_MODE1,OUTPUT); + digitalWrite(PIN_A5995_MODE2,LOW); + pinMode(PIN_A5995_MODE2,OUTPUT); + digitalWrite(PIN_A5995_PHASE1,LOW); + pinMode(PIN_A5995_PHASE1,OUTPUT); + digitalWrite(PIN_A5995_PHASE2,LOW); + pinMode(PIN_A5995_PHASE2,OUTPUT); + + digitalWrite(PIN_A5995_SLEEPn,HIGH); + pinMode(PIN_A5995_SLEEPn,OUTPUT); + + + + //setup the PWM for current on the A4954, set for low current + digitalWrite(PIN_A5995_VREF1,LOW); + digitalWrite(PIN_A5995_VREF2,LOW); + pinMode(PIN_A5995_VREF1, OUTPUT); + pinMode(PIN_A5995_VREF2, OUTPUT); + + enabled=true; + lastStepMicros=0; + forwardRotation=true; + + setupDAC(); + + +// +// GPIO_HIGH(PIN_A5995_ENABLE1); +// GPIO_HIGH(PIN_A5995_ENABLE2); +// GPIO_LOW(PIN_A5995_MODE1); +// GPIO_LOW(PIN_A5995_MODE2); +// GPIO_HIGH(PIN_A5995_PHASE1); +// GPIO_HIGH(PIN_A5995_PHASE2); +// int i=0;; +// while (1) +// { +// int32_t x; +// WARNING("MA %d",i); +// x=(int32_t)((int64_t)i*(DAC_MAX))/3300; +// setDAC(x,x); +// delay(1000); +// i=i+10; +// if (i>1000) +// { +// i=0; +// } +// +// } + + + return; +} + + + +void A5995::enable(bool enable) +{ + enabled=enable; + if (enabled == false) + { + WARNING("A4954 disabled"); + setDAC(0,0); //turn current off + GPIO_LOW(PIN_A5995_ENABLE1); + GPIO_LOW(PIN_A5995_ENABLE2); + GPIO_LOW(PIN_A5995_MODE1); + GPIO_LOW(PIN_A5995_MODE2); + GPIO_LOW(PIN_A5995_PHASE1); + GPIO_LOW(PIN_A5995_PHASE2); + } +} + + + +//this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step. +// stepAngle is in A4954_NUM_MICROSTEPS units.. +// The A4954 has no idea where the motor is, so the calling function has to +// to tell the A4954 what phase to drive motor coils. +// A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees +// Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you +// currently are. +int32_t A5995::move(int32_t stepAngle, uint32_t mA) +{ + uint16_t angle; + int32_t cos,sin; + int32_t dacSin,dacCos; + static int32_t lastSin=0,lastCos=0; + static int i=1; + + if (enabled == false) + { + WARNING("A4954 disabled"); + setDAC(0,0); //turn current off + GPIO_LOW(PIN_A5995_ENABLE1); + GPIO_LOW(PIN_A5995_ENABLE2); + GPIO_LOW(PIN_A5995_MODE1); + GPIO_LOW(PIN_A5995_MODE2); + GPIO_LOW(PIN_A5995_PHASE1); + GPIO_LOW(PIN_A5995_PHASE2); + return stepAngle; + } + + //WARNING("move %d %d",stepAngle,mA); + + stepAngle=(stepAngle) % SINE_STEPS; + //figure out our sine Angle + // note our SINE_STEPS is 4x of microsteps for a reason + //angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS; + angle=stepAngle; + + if (i==0) + { + WARNING("angle %d ",angle); + } + //calculate the sine and cosine of our angle + sin=sine(angle); + cos=cosine(angle); + + //if we are reverse swap the sign of one of the angels + if (false == forwardRotation) + { + cos=-cos; + } + + //scale sine result by current(mA) + dacSin=((int32_t)mA*(int64_t)(sin))/SINE_MAX; + + if (i==0) + { + WARNING("dacsine %d ",dacSin); + } +// if ((lastSin-dacSin)>100) //decreasing current +// { +// GPIO_LOW(PIN_A5995_MODE2); //fast decay +// } else +// { +// GPIO_HIGH(PIN_A5995_MODE2); //slow decay +// } + lastSin=dacSin; + + //convert value into DAC scaled to 3300mA max + dacSin=(int32_t)((int64_t)abs(dacSin)*(DAC_MAX))/3300; + + + //scale cosine result by current(mA) + dacCos=((int32_t)mA*(int64_t)(cos))/SINE_MAX; + + if (i==0) + { + WARNING("daccos %d ",dacCos); + } +// if ((lastCos-dacCos)>100) //decreasing current +// { +// GPIO_LOW(PIN_A5995_MODE1); //fast decay +// } else +// { +// GPIO_HIGH(PIN_A5995_MODE1); //slow decay +// } + lastCos=dacCos; + + //convert value into DAC scaled to 3300mA max + dacCos=(int32_t)((int64_t)abs(dacCos)*(DAC_MAX))/3300; + + +if (i==0) +{ + WARNING("dacs are %d %d",dacSin,dacCos); +} + setDAC(dacSin,dacCos); + + GPIO_HIGH(PIN_A5995_ENABLE1); + GPIO_HIGH(PIN_A5995_ENABLE2); + GPIO_LOW(PIN_A5995_MODE1); + GPIO_LOW(PIN_A5995_MODE2); + + +if (i==0) +{ + WARNING("sins are %d %d",sin,cos); +} + + if (sin>0) + { + GPIO_HIGH(PIN_A5995_PHASE2); + }else + { + GPIO_LOW(PIN_A5995_PHASE2); + + } + if (cos>0) + { + GPIO_HIGH(PIN_A5995_PHASE1); + + }else + { + GPIO_LOW(PIN_A5995_PHASE1); + + } + +// i++; +// if (i>3000) i=0; + // YELLOW_LED(led); + // led=(led+1) & 0x01; + lastStepMicros=micros(); + return stepAngle; +} +#pragma GCC pop_options + + + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.h b/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.h new file mode 100644 index 0000000..756513c --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.h @@ -0,0 +1,92 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#ifndef A5995_H_ +#define A5995_H_ + +#include +#include "board.h" +#include "angle.h" +#include "sine.h" + +#define A5995_NUM_MICROSTEPS (256) + + +//prevent someone for making a mistake with the code +#if ((A5995_NUM_MICROSTEPS*4) != SINE_STEPS) +#error "SINE_STEPS must be 4x of Micro steps for the move function" +#endif + + + +/* + * When it comes to the stepper driver if we use angles + * we will always have a rounding error. For example + * a 0-65536(360) angle for 1.8 degree step is 327.68 so + * if you increment 200 of these as 327 you have a 13.6 error + * after one rotation. + * If you use floating point the effect is the same but takes longer. + * + * The only error-less accumulation system is to use native units, ie full + * steps and microsteps. + * + */ + +class A5995 +{ +private: + uint32_t lastStepMicros; // time in microseconds that last step happened + bool forwardRotation=true; + volatile bool enabled=true; + +public: + void begin(void); + + //moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step. + int32_t move(int32_t stepAngle, uint32_t mA); + + uint32_t microsSinceStep(void) {return micros()-lastStepMicros;}; + void setRotationDirection(bool forward) {forwardRotation=forward;}; + + void enable(bool enable); + void limitCurrent(uint8_t percent) {return;}; //Not used +}; + + + +#endif /* A5995_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_GFX.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_GFX.cpp new file mode 100644 index 0000000..46d4d54 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_GFX.cpp @@ -0,0 +1,1071 @@ +/* +This is the core graphics library for all our displays, providing a common +set of graphics primitives (points, lines, circles, etc.). It needs to be +paired with a hardware-specific library for each display device we carry +(to handle the lower-level functions). + +Adafruit invests time and resources providing this open source code, please +support Adafruit & open-source hardware by purchasing products from Adafruit! + +Copyright (c) 2013 Adafruit Industries. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef __AVR__ + #include +#elif defined(ESP8266) + #include +#endif +#include "Adafruit_GFX.h" +#include "glcdfont.c" + +// Many (but maybe not all) non-AVR board installs define macros +// for compatibility with existing PROGMEM-reading AVR code. +// Do our own checks and defines here for good measure... + +#ifndef pgm_read_byte + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#endif +#ifndef pgm_read_word + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) +#endif +#ifndef pgm_read_dword + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#endif + +// Pointers are a peculiar case...typically 16-bit on AVR boards, +// 32 bits elsewhere. Try to accommodate both... + +#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF) + #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr)) +#else + #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef _swap_int16_t +#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } +#endif + +Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h): + WIDTH(w), HEIGHT(h) +{ + _width = WIDTH; + _height = HEIGHT; + rotation = 0; + cursor_y = cursor_x = 0; + textsize = 1; + textcolor = textbgcolor = 0xFFFF; + wrap = true; + _cp437 = false; + gfxFont = NULL; +} + +// Draw a circle outline +void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r, + uint16_t color) { + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + drawPixel(x0 , y0+r, color); + drawPixel(x0 , y0-r, color); + drawPixel(x0+r, y0 , color); + drawPixel(x0-r, y0 , color); + + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + drawPixel(x0 + x, y0 + y, color); + drawPixel(x0 - x, y0 + y, color); + drawPixel(x0 + x, y0 - y, color); + drawPixel(x0 - x, y0 - y, color); + drawPixel(x0 + y, y0 + x, color); + drawPixel(x0 - y, y0 + x, color); + drawPixel(x0 + y, y0 - x, color); + drawPixel(x0 - y, y0 - x, color); + } +} + +void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0, + int16_t r, uint8_t cornername, uint16_t color) { + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + if (cornername & 0x4) { + drawPixel(x0 + x, y0 + y, color); + drawPixel(x0 + y, y0 + x, color); + } + if (cornername & 0x2) { + drawPixel(x0 + x, y0 - y, color); + drawPixel(x0 + y, y0 - x, color); + } + if (cornername & 0x8) { + drawPixel(x0 - y, y0 + x, color); + drawPixel(x0 - x, y0 + y, color); + } + if (cornername & 0x1) { + drawPixel(x0 - y, y0 - x, color); + drawPixel(x0 - x, y0 - y, color); + } + } +} + +void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r, + uint16_t color) { + drawFastVLine(x0, y0-r, 2*r+1, color); + fillCircleHelper(x0, y0, r, 3, 0, color); +} + +// Used to do circles and roundrects +void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, + uint8_t cornername, int16_t delta, uint16_t color) { + + int16_t f = 1 - r; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * r; + int16_t x = 0; + int16_t y = r; + + while (x= 0) { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) { + drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); + } + if (cornername & 0x2) { + drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); + drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); + } + } +} + +// Bresenham's algorithm - thx wikpedia +void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, + uint16_t color) { + int16_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + _swap_int16_t(x0, y0); + _swap_int16_t(x1, y1); + } + + if (x0 > x1) { + _swap_int16_t(x0, x1); + _swap_int16_t(y0, y1); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + for (; x0<=x1; x0++) { + if (steep) { + drawPixel(y0, x0, color); + } else { + drawPixel(x0, y0, color); + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } + } +} + +// Draw a rectangle +void Adafruit_GFX::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, + uint16_t color) { + drawFastHLine(x, y, w, color); + drawFastHLine(x, y+h-1, w, color); + drawFastVLine(x, y, h, color); + drawFastVLine(x+w-1, y, h, color); +} + +void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, + int16_t h, uint16_t color) { + // Update in subclasses if desired! + drawLine(x, y, x, y+h-1, color); +} + +void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y, + int16_t w, uint16_t color) { + // Update in subclasses if desired! + drawLine(x, y, x+w-1, y, color); +} + +void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, + uint16_t color) { + // Update in subclasses if desired! + for (int16_t i=x; i= y1 >= y0) + if (y0 > y1) { + _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); + } + if (y1 > y2) { + _swap_int16_t(y2, y1); _swap_int16_t(x2, x1); + } + if (y0 > y1) { + _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); + } + + if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing + a = b = x0; + if(x1 < a) a = x1; + else if(x1 > b) b = x1; + if(x2 < a) a = x2; + else if(x2 > b) b = x2; + drawFastHLine(a, y0, b-a+1, color); + return; + } + + int16_t + dx01 = x1 - x0, + dy01 = y1 - y0, + dx02 = x2 - x0, + dy02 = y2 - y0, + dx12 = x2 - x1, + dy12 = y2 - y1; + int32_t + sa = 0, + sb = 0; + + // For upper part of triangle, find scanline crossings for segments + // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 + // is included here (and second loop will be skipped, avoiding a /0 + // error there), otherwise scanline y1 is skipped here and handled + // in the second loop...which also avoids a /0 error here if y0=y1 + // (flat-topped triangle). + if(y1 == y2) last = y1; // Include y1 scanline + else last = y1-1; // Skip it + + for(y=y0; y<=last; y++) { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + /* longhand: + a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) _swap_int16_t(a,b); + drawFastHLine(a, y, b-a+1, color); + } + + // For lower part of triangle, find scanline crossings for segments + // 0-2 and 1-2. This loop is skipped if y1=y2. + sa = dx12 * (y - y1); + sb = dx02 * (y - y0); + for(; y<=y2; y++) { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + /* longhand: + a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) _swap_int16_t(a,b); + drawFastHLine(a, y, b-a+1, color); + } +} + +// Draw a 1-bit image (bitmap) at the specified (x,y) position from the +// provided bitmap buffer (must be PROGMEM memory) using the specified +// foreground color (unset bits are transparent). +void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, + const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { + + int16_t i, j, byteWidth = (w + 7) / 8; + uint8_t byte; + + for(j=0; j>= 1; + else byte = pgm_read_byte(bitmap + j * byteWidth + i / 8); + if(byte & 0x01) drawPixel(x+i, y+j, color); + } + } +} + +#if ARDUINO >= 100 +size_t Adafruit_GFX::write(uint8_t c) { +#else +void Adafruit_GFX::write(uint8_t c) { +#endif + + if(!gfxFont) { // 'Classic' built-in font + + if(c == '\n') { + cursor_y += textsize*8; + cursor_x = 0; + } else if(c == '\r') { + // skip em + } else { + if(wrap && ((cursor_x + textsize * 6) >= _width)) { // Heading off edge? + cursor_x = 0; // Reset x to zero + cursor_y += textsize * 8; // Advance y one line + } + drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + cursor_x += textsize * 6; + } + + } else { // Custom font + + if(c == '\n') { + cursor_x = 0; + cursor_y += (int16_t)textsize * + (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } else if(c != '\r') { + uint8_t first = pgm_read_byte(&gfxFont->first); + if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) { + uint8_t c2 = c - pgm_read_byte(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c2]); + uint8_t w = pgm_read_byte(&glyph->width), + h = pgm_read_byte(&glyph->height); + if((w > 0) && (h > 0)) { // Is there an associated bitmap? + int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic + if(wrap && ((cursor_x + textsize * (xo + w)) >= _width)) { + // Drawing character would go off right edge; wrap to new line + cursor_x = 0; + cursor_y += (int16_t)textsize * + (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } + drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + } + cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; + } + } + + } +#if ARDUINO >= 100 + return 1; +#endif +} + +// Draw a character +void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c, + uint16_t color, uint16_t bg, uint8_t size) { + + if(!gfxFont) { // 'Classic' built-in font + + if((x >= _width) || // Clip right + (y >= _height) || // Clip bottom + ((x + 6 * size - 1) < 0) || // Clip left + ((y + 8 * size - 1) < 0)) // Clip top + return; + + if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior + + for(int8_t i=0; i<6; i++ ) { + uint8_t line; + if(i < 5) line = pgm_read_byte(font+(c*5)+i); + else line = 0x0; + for(int8_t j=0; j<8; j++, line >>= 1) { + if(line & 0x1) { + if(size == 1) drawPixel(x+i, y+j, color); + else fillRect(x+(i*size), y+(j*size), size, size, color); + } else if(bg != color) { + if(size == 1) drawPixel(x+i, y+j, bg); + else fillRect(x+i*size, y+j*size, size, size, bg); + } + } + } + + } else { // Custom font + + // Character is assumed previously filtered by write() to eliminate + // newlines, returns, non-printable characters, etc. Calling drawChar() + // directly with 'bad' characters of font may cause mayhem! + + c -= pgm_read_byte(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); + uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); + + uint16_t bo = pgm_read_word(&glyph->bitmapOffset); + uint8_t w = pgm_read_byte(&glyph->width), + h = pgm_read_byte(&glyph->height), + xa = pgm_read_byte(&glyph->xAdvance); + int8_t xo = pgm_read_byte(&glyph->xOffset), + yo = pgm_read_byte(&glyph->yOffset); + uint8_t xx, yy, bits, bit = 0; + int16_t xo16, yo16; + + if(size > 1) { + xo16 = xo; + yo16 = yo; + } + + // Todo: Add character clipping here + + // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS. + // THIS IS ON PURPOSE AND BY DESIGN. The background color feature + // has typically been used with the 'classic' font to overwrite old + // screen contents with new data. This ONLY works because the + // characters are a uniform size; it's not a sensible thing to do with + // proportionally-spaced fonts with glyphs of varying sizes (and that + // may overlap). To replace previously-drawn text when using a custom + // font, use the getTextBounds() function to determine the smallest + // rectangle encompassing a string, erase the area with fillRect(), + // then draw new text. This WILL infortunately 'blink' the text, but + // is unavoidable. Drawing 'background' pixels will NOT fix this, + // only creates a new set of problems. Have an idea to work around + // this (a canvas object type for MCUs that can afford the RAM and + // displays supporting setAddrWindow() and pushColors()), but haven't + // implemented this yet. + + for(yy=0; yy 0) ? s : 1; +} + +void Adafruit_GFX::setTextColor(uint16_t c) { + // For 'transparent' background, we'll set the bg + // to the same as fg instead of using a flag + textcolor = textbgcolor = c; +} + +void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) { + textcolor = c; + textbgcolor = b; +} + +void Adafruit_GFX::setTextWrap(boolean w) { + wrap = w; +} + +uint8_t Adafruit_GFX::getRotation(void) const { + return rotation; +} + +void Adafruit_GFX::setRotation(uint8_t x) { + rotation = (x & 3); + switch(rotation) { + case 0: + case 2: + _width = WIDTH; + _height = HEIGHT; + break; + case 1: + case 3: + _width = HEIGHT; + _height = WIDTH; + break; + } +} + +// Enable (or disable) Code Page 437-compatible charset. +// There was an error in glcdfont.c for the longest time -- one character +// (#176, the 'light shade' block) was missing -- this threw off the index +// of every character that followed it. But a TON of code has been written +// with the erroneous character indices. By default, the library uses the +// original 'wrong' behavior and old sketches will still work. Pass 'true' +// to this function to use correct CP437 character values in your code. +void Adafruit_GFX::cp437(boolean x) { + _cp437 = x; +} + +void Adafruit_GFX::setFont(const GFXfont *f) { + if(f) { // Font struct pointer passed in? + if(!gfxFont) { // And no current font struct? + // Switching from classic to new font behavior. + // Move cursor pos down 6 pixels so it's on baseline. + cursor_y += 6; + } + } else if(gfxFont) { // NULL passed. Current font struct defined? + // Switching from new to classic font behavior. + // Move cursor pos up 6 pixels so it's at top-left of char. + cursor_y -= 6; + } + gfxFont = (GFXfont *)f; +} + +// Pass string and a cursor position, returns UL corner and W,H. +void Adafruit_GFX::getTextBounds(char *str, int16_t x, int16_t y, + int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) { + uint8_t c; // Current character + + *x1 = x; + *y1 = y; + *w = *h = 0; + + if(gfxFont) { + + GFXglyph *glyph; + uint8_t first = pgm_read_byte(&gfxFont->first), + last = pgm_read_byte(&gfxFont->last), + gw, gh, xa; + int8_t xo, yo; + int16_t minx = _width, miny = _height, maxx = -1, maxy = -1, + gx1, gy1, gx2, gy2, ts = (int16_t)textsize, + ya = ts * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + + while((c = *str++)) { + if(c != '\n') { // Not a newline + if(c != '\r') { // Not a carriage return, is normal char + if((c >= first) && (c <= last)) { // Char present in current font + c -= first; + glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); + gw = pgm_read_byte(&glyph->width); + gh = pgm_read_byte(&glyph->height); + xa = pgm_read_byte(&glyph->xAdvance); + xo = pgm_read_byte(&glyph->xOffset); + yo = pgm_read_byte(&glyph->yOffset); + if(wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) { + // Line wrap + x = 0; // Reset x to 0 + y += ya; // Advance y by 1 line + } + gx1 = x + xo * ts; + gy1 = y + yo * ts; + gx2 = gx1 + gw * ts - 1; + gy2 = gy1 + gh * ts - 1; + if(gx1 < minx) minx = gx1; + if(gy1 < miny) miny = gy1; + if(gx2 > maxx) maxx = gx2; + if(gy2 > maxy) maxy = gy2; + x += xa * ts; + } + } // Carriage return = do nothing + } else { // Newline + x = 0; // Reset x + y += ya; // Advance y by 1 line + } + } + // End of string + *x1 = minx; + *y1 = miny; + if(maxx >= minx) *w = maxx - minx + 1; + if(maxy >= miny) *h = maxy - miny + 1; + + } else { // Default font + + uint16_t lineWidth = 0, maxWidth = 0; // Width of current, all lines + + while((c = *str++)) { + if(c != '\n') { // Not a newline + if(c != '\r') { // Not a carriage return, is normal char + if(wrap && ((x + textsize * 6) >= _width)) { + x = 0; // Reset x to 0 + y += textsize * 8; // Advance y by 1 line + if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line + lineWidth = textsize * 6; // First char on new line + } else { // No line wrap, just keep incrementing X + lineWidth += textsize * 6; // Includes interchar x gap + } + } // Carriage return = do nothing + } else { // Newline + x = 0; // Reset x to 0 + y += textsize * 8; // Advance y by 1 line + if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line + lineWidth = 0; // Reset lineWidth for new line + } + } + // End of string + if(lineWidth) y += textsize * 8; // Add height of last (or only) line + if(lineWidth > maxWidth) maxWidth = lineWidth; // Is the last or only line the widest? + *w = maxWidth - 1; // Don't include last interchar x gap + *h = y - *y1; + + } // End classic vs custom font +} + +// Same as above, but for PROGMEM strings +void Adafruit_GFX::getTextBounds(const __FlashStringHelper *str, + int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) { + uint8_t *s = (uint8_t *)str, c; + + *x1 = x; + *y1 = y; + *w = *h = 0; + + if(gfxFont) { + + GFXglyph *glyph; + uint8_t first = pgm_read_byte(&gfxFont->first), + last = pgm_read_byte(&gfxFont->last), + gw, gh, xa; + int8_t xo, yo; + int16_t minx = _width, miny = _height, maxx = -1, maxy = -1, + gx1, gy1, gx2, gy2, ts = (int16_t)textsize, + ya = ts * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + + while((c = pgm_read_byte(s++))) { + if(c != '\n') { // Not a newline + if(c != '\r') { // Not a carriage return, is normal char + if((c >= first) && (c <= last)) { // Char present in current font + c -= first; + glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); + gw = pgm_read_byte(&glyph->width); + gh = pgm_read_byte(&glyph->height); + xa = pgm_read_byte(&glyph->xAdvance); + xo = pgm_read_byte(&glyph->xOffset); + yo = pgm_read_byte(&glyph->yOffset); + if(wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) { + // Line wrap + x = 0; // Reset x to 0 + y += ya; // Advance y by 1 line + } + gx1 = x + xo * ts; + gy1 = y + yo * ts; + gx2 = gx1 + gw * ts - 1; + gy2 = gy1 + gh * ts - 1; + if(gx1 < minx) minx = gx1; + if(gy1 < miny) miny = gy1; + if(gx2 > maxx) maxx = gx2; + if(gy2 > maxy) maxy = gy2; + x += xa * ts; + } + } // Carriage return = do nothing + } else { // Newline + x = 0; // Reset x + y += ya; // Advance y by 1 line + } + } + // End of string + *x1 = minx; + *y1 = miny; + if(maxx >= minx) *w = maxx - minx + 1; + if(maxy >= miny) *h = maxy - miny + 1; + + } else { // Default font + + uint16_t lineWidth = 0, maxWidth = 0; // Width of current, all lines + + while((c = pgm_read_byte(s++))) { + if(c != '\n') { // Not a newline + if(c != '\r') { // Not a carriage return, is normal char + if(wrap && ((x + textsize * 6) >= _width)) { + x = 0; // Reset x to 0 + y += textsize * 8; // Advance y by 1 line + if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line + lineWidth = textsize * 6; // First char on new line + } else { // No line wrap, just keep incrementing X + lineWidth += textsize * 6; // Includes interchar x gap + } + } // Carriage return = do nothing + } else { // Newline + x = 0; // Reset x to 0 + y += textsize * 8; // Advance y by 1 line + if(lineWidth > maxWidth) maxWidth = lineWidth; // Save widest line + lineWidth = 0; // Reset lineWidth for new line + } + } + // End of string + if(lineWidth) y += textsize * 8; // Add height of last (or only) line + if(lineWidth > maxWidth) maxWidth = lineWidth; // Is the last or only line the widest? + *w = maxWidth - 1; // Don't include last interchar x gap + *h = y - *y1; + + } // End classic vs custom font +} + +// Return the size of the display (per current rotation) +int16_t Adafruit_GFX::width(void) const { + return _width; +} + +int16_t Adafruit_GFX::height(void) const { + return _height; +} + +void Adafruit_GFX::invertDisplay(boolean i) { + // Do nothing, must be subclassed if supported by hardware +} + +/***************************************************************************/ +// code for the GFX button UI element + +Adafruit_GFX_Button::Adafruit_GFX_Button(void) { + _gfx = 0; +} + +void Adafruit_GFX_Button::initButton( + Adafruit_GFX *gfx, int16_t x, int16_t y, uint8_t w, uint8_t h, + uint16_t outline, uint16_t fill, uint16_t textcolor, + char *label, uint8_t textsize) +{ + _x = x; + _y = y; + _w = w; + _h = h; + _outlinecolor = outline; + _fillcolor = fill; + _textcolor = textcolor; + _textsize = textsize; + _gfx = gfx; + strncpy(_label, label, 9); + _label[9] = 0; +} + +void Adafruit_GFX_Button::drawButton(boolean inverted) { + uint16_t fill, outline, text; + + if(!inverted) { + fill = _fillcolor; + outline = _outlinecolor; + text = _textcolor; + } else { + fill = _textcolor; + outline = _outlinecolor; + text = _fillcolor; + } + + _gfx->fillRoundRect(_x - (_w/2), _y - (_h/2), _w, _h, min(_w,_h)/4, fill); + _gfx->drawRoundRect(_x - (_w/2), _y - (_h/2), _w, _h, min(_w,_h)/4, outline); + + _gfx->setCursor(_x - strlen(_label)*3*_textsize, _y-4*_textsize); + _gfx->setTextColor(text); + _gfx->setTextSize(_textsize); + _gfx->print(_label); +} + +boolean Adafruit_GFX_Button::contains(int16_t x, int16_t y) { + if ((x < (_x - _w/2)) || (x > (_x + _w/2))) return false; + if ((y < (_y - _h/2)) || (y > (_y + _h/2))) return false; + return true; +} + +void Adafruit_GFX_Button::press(boolean p) { + laststate = currstate; + currstate = p; +} + +boolean Adafruit_GFX_Button::isPressed() { return currstate; } +boolean Adafruit_GFX_Button::justPressed() { return (currstate && !laststate); } +boolean Adafruit_GFX_Button::justReleased() { return (!currstate && laststate); } + +// ------------------------------------------------------------------------- + +// GFXcanvas1 and GFXcanvas16 (currently a WIP, don't get too comfy with the +// implementation) provide 1- and 16-bit offscreen canvases, the address of +// which can be passed to drawBitmap() or pushColors() (the latter appears +// to only be in Adafruit_TFTLCD at this time). This is here mostly to +// help with the recently-added proportionally-spaced fonts; adds a way to +// refresh a section of the screen without a massive flickering clear-and- +// redraw...but maybe you'll find other uses too. VERY RAM-intensive, since +// the buffer is in MCU memory and not the display driver...GXFcanvas1 might +// be minimally useful on an Uno-class board, but this and GFXcanvas16 are +// much more likely to require at least a Mega or various recent ARM-type +// boards (recomment, as the text+bitmap draw can be pokey). GFXcanvas1 +// requires 1 bit per pixel (rounded up to nearest byte per scanline), +// GFXcanvas16 requires 2 bytes per pixel (no scanline pad). +// NOT EXTENSIVELY TESTED YET. MAY CONTAIN WORST BUGS KNOWN TO HUMANKIND. + +GFXcanvas1::GFXcanvas1(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { + uint16_t bytes = ((w + 7) / 8) * h; + if((buffer = (uint8_t *)malloc(bytes))) { + memset(buffer, 0, bytes); + } +} + +GFXcanvas1::~GFXcanvas1(void) { + if(buffer) free(buffer); +} + +uint8_t* GFXcanvas1::getBuffer(void) { + return buffer; +} + +void GFXcanvas1::drawPixel(int16_t x, int16_t y, uint16_t color) { + // Bitmask tables of 0x80>>X and ~(0x80>>X), because X>>Y is slow on AVR + static const uint8_t PROGMEM + GFXsetBit[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }, + GFXclrBit[] = { 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE }; + + if(buffer) { + if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; + + int16_t t; + switch(rotation) { + case 1: + t = x; + x = WIDTH - 1 - y; + y = t; + break; + case 2: + x = WIDTH - 1 - x; + y = HEIGHT - 1 - y; + break; + case 3: + t = x; + x = y; + y = HEIGHT - 1 - t; + break; + } + + uint8_t *ptr = &buffer[(x / 8) + y * ((WIDTH + 7) / 8)]; + if(color) *ptr |= pgm_read_byte(&GFXsetBit[x & 7]); + else *ptr &= pgm_read_byte(&GFXclrBit[x & 7]); + } +} + +void GFXcanvas1::fillScreen(uint16_t color) { + if(buffer) { + uint16_t bytes = ((WIDTH + 7) / 8) * HEIGHT; + memset(buffer, color ? 0xFF : 0x00, bytes); + } +} + +GFXcanvas16::GFXcanvas16(uint16_t w, uint16_t h) : Adafruit_GFX(w, h) { + uint16_t bytes = w * h * 2; + if((buffer = (uint16_t *)malloc(bytes))) { + memset(buffer, 0, bytes); + } +} + +GFXcanvas16::~GFXcanvas16(void) { + if(buffer) free(buffer); +} + +uint16_t* GFXcanvas16::getBuffer(void) { + return buffer; +} + +void GFXcanvas16::drawPixel(int16_t x, int16_t y, uint16_t color) { + if(buffer) { + if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return; + + int16_t t; + switch(rotation) { + case 1: + t = x; + x = WIDTH - 1 - y; + y = t; + break; + case 2: + x = WIDTH - 1 - x; + y = HEIGHT - 1 - y; + break; + case 3: + t = x; + x = y; + y = HEIGHT - 1 - t; + break; + } + + buffer[x + y * WIDTH] = color; + } +} + +void GFXcanvas16::fillScreen(uint16_t color) { + if(buffer) { + uint8_t hi = color >> 8, lo = color & 0xFF; + if(hi == lo) { + memset(buffer, lo, WIDTH * HEIGHT * 2); + } else { + uint16_t i, pixels = WIDTH * HEIGHT; + for(i=0; i= 100 + #include "Arduino.h" + #include "Print.h" +#else + #include "WProgram.h" +#endif + +#include "gfxfont.h" + +class Adafruit_GFX : public Print { + + public: + + Adafruit_GFX(int16_t w, int16_t h); // Constructor + + // This MUST be defined by the subclass: + virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0; + + // These MAY be overridden by the subclass to provide device-specific + // optimized code. Otherwise 'generic' versions are used. + virtual void + drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color), + drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color), + drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color), + drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), + fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color), + fillScreen(uint16_t color), + invertDisplay(boolean i); + + // These exist only with Adafruit_GFX (no subclass overrides) + void + drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), + drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, + uint16_t color), + fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color), + fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, + int16_t delta, uint16_t color), + drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint16_t color), + fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, + int16_t x2, int16_t y2, uint16_t color), + drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, + int16_t radius, uint16_t color), + fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, + int16_t radius, uint16_t color), + drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, + int16_t w, int16_t h, uint16_t color), + drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, + int16_t w, int16_t h, uint16_t color, uint16_t bg), + drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, + int16_t w, int16_t h, uint16_t color), + drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, + int16_t w, int16_t h, uint16_t color, uint16_t bg), + drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, + int16_t w, int16_t h, uint16_t color), + drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, + uint16_t bg, uint8_t size), + setCursor(int16_t x, int16_t y), + setTextColor(uint16_t c), + setTextColor(uint16_t c, uint16_t bg), + setTextSize(uint8_t s), + setTextWrap(boolean w), + setRotation(uint8_t r), + cp437(boolean x=true), + setFont(const GFXfont *f = NULL), + getTextBounds(char *string, int16_t x, int16_t y, + int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h), + getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, + int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); + +#if ARDUINO >= 100 + virtual size_t write(uint8_t); +#else + virtual void write(uint8_t); +#endif + + int16_t height(void) const; + int16_t width(void) const; + + uint8_t getRotation(void) const; + + // get current cursor position (get rotation safe maximum values, using: width() for x, height() for y) + int16_t getCursorX(void) const; + int16_t getCursorY(void) const; + + protected: + const int16_t + WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes + int16_t + _width, _height, // Display w/h as modified by current rotation + cursor_x, cursor_y; + uint16_t + textcolor, textbgcolor; + uint8_t + textsize, + rotation; + boolean + wrap, // If set, 'wrap' text at right edge of display + _cp437; // If set, use correct CP437 charset (default is off) + GFXfont + *gfxFont; +}; + +class Adafruit_GFX_Button { + + public: + Adafruit_GFX_Button(void); + void initButton(Adafruit_GFX *gfx, int16_t x, int16_t y, + uint8_t w, uint8_t h, uint16_t outline, uint16_t fill, + uint16_t textcolor, char *label, uint8_t textsize); + void drawButton(boolean inverted = false); + boolean contains(int16_t x, int16_t y); + + void press(boolean p); + boolean isPressed(); + boolean justPressed(); + boolean justReleased(); + + private: + Adafruit_GFX *_gfx; + int16_t _x, _y; + uint16_t _w, _h; + uint8_t _textsize; + uint16_t _outlinecolor, _fillcolor, _textcolor; + char _label[10]; + + boolean currstate, laststate; +}; + +class GFXcanvas1 : public Adafruit_GFX { + + public: + GFXcanvas1(uint16_t w, uint16_t h); + ~GFXcanvas1(void); + void drawPixel(int16_t x, int16_t y, uint16_t color), + fillScreen(uint16_t color); + uint8_t *getBuffer(void); + private: + uint8_t *buffer; +}; + +class GFXcanvas16 : public Adafruit_GFX { + GFXcanvas16(uint16_t w, uint16_t h); + ~GFXcanvas16(void); + void drawPixel(int16_t x, int16_t y, uint16_t color), + fillScreen(uint16_t color); + uint16_t *getBuffer(void); + private: + uint16_t *buffer; +}; + +#endif // _ADAFRUIT_GFX_H diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.cpp new file mode 100644 index 0000000..2a78892 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.cpp @@ -0,0 +1,750 @@ +/********************************************************************* +This is a library for our Monochrome OLEDs based on SSD1306 drivers + + Pick one up today in the adafruit shop! + ------> http://www.adafruit.com/category/63_98 + +These displays use SPI to communicate, 4 or 5 pins are required to +interface + +Adafruit invests time and resources providing this open source code, +please support Adafruit and open-source hardware by purchasing +products from Adafruit! + +Written by Limor Fried/Ladyada for Adafruit Industries. +BSD license, check license.txt for more information +All text above, and the splash screen below must be included in any redistribution + *********************************************************************/ + +#ifdef __AVR__ +#include +#elif defined(ESP8266) +#include +#else +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#endif + +#if !defined(__ARM_ARCH) && !defined(ENERGIA) && !defined(ESP8266) +#include +#endif + +#include + +#include +#include +#include "Adafruit_GFX.h" +#include "Adafruit_SSD1306.h" +#include "syslog.h" + +// the memory buffer for the LCD + +static uint8_t buffer[SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH / 8] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0xFF, +#if (SSD1306_LCDHEIGHT * SSD1306_LCDWIDTH > 96*16) + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, + 0x80, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x8C, 0x8E, 0x84, 0x00, 0x00, 0x80, 0xF8, + 0xF8, 0xF8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, + 0x00, 0xE0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xC7, 0x01, 0x01, + 0x01, 0x01, 0x83, 0xFF, 0xFF, 0x00, 0x00, 0x7C, 0xFE, 0xC7, 0x01, 0x01, 0x01, 0x01, 0x83, 0xFF, + 0xFF, 0xFF, 0x00, 0x38, 0xFE, 0xC7, 0x83, 0x01, 0x01, 0x01, 0x83, 0xC7, 0xFF, 0xFF, 0x00, 0x00, + 0x01, 0xFF, 0xFF, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x07, 0x01, 0x01, 0x01, 0x00, 0x00, 0x7F, 0xFF, + 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x0F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x8F, + 0x8F, 0x9F, 0xBF, 0xFF, 0xFF, 0xC3, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, + 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xC0, 0x00, 0x01, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x01, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, + 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03, 0x00, 0x00, + 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03, + 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +#if (SSD1306_LCDHEIGHT == 64) + 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F, + 0x87, 0xC7, 0xF7, 0xFF, 0xFF, 0x1F, 0x1F, 0x3D, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7D, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x00, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F, + 0x0F, 0x07, 0x1F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xE0, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, + 0x00, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x0E, 0xFC, 0xF8, 0x00, 0x00, 0xF0, 0xF8, 0x1C, 0x0E, + 0x06, 0x06, 0x06, 0x0C, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFC, + 0xFE, 0xFC, 0x00, 0x18, 0x3C, 0x7E, 0x66, 0xE6, 0xCE, 0x84, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0x06, + 0x06, 0xFC, 0xFE, 0xFC, 0x0C, 0x06, 0x06, 0x06, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xC0, 0xF8, + 0xFC, 0x4E, 0x46, 0x46, 0x46, 0x4E, 0x7C, 0x78, 0x40, 0x18, 0x3C, 0x76, 0xE6, 0xCE, 0xCC, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, + 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x0C, + 0x18, 0x18, 0x0C, 0x06, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x01, 0x0F, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, + 0x07, 0x01, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, + 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x07, + 0x07, 0x0C, 0x0C, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x00, 0x04, 0x0E, 0x0C, 0x18, 0x0C, 0x0F, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +#endif +#endif +}; + +#define ssd1306_swap(a, b) { int16_t t = a; a = b; b = t; } + +// the most basic function, set a single pixel +void Adafruit_SSD1306::drawPixel(int16_t x, int16_t y, uint16_t color) { + if ((x < 0) || (x >= width()) || (y < 0) || (y >= height())) + return; + + // check rotation, move pixel around if necessary + switch (getRotation()) { + case 1: + ssd1306_swap(x, y); + x = WIDTH - x - 1; + break; + case 2: + x = WIDTH - x - 1; + y = HEIGHT - y - 1; + break; + case 3: + ssd1306_swap(x, y); + y = HEIGHT - y - 1; + break; + } + + // x is which column + switch (color) + { + case WHITE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7)); break; + case BLACK: buffer[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); break; + case INVERSE: buffer[x+ (y/8)*SSD1306_LCDWIDTH] ^= (1 << (y&7)); break; + } + +} + +Adafruit_SSD1306::Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) { + cs = CS; + rst = RST; + dc = DC; + sclk = SCLK; + sid = SID; + hwSPI = false; +} + +// constructor for hardware SPI - we indicate DataCommand, ChipSelect, Reset +Adafruit_SSD1306::Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS) : Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) { + dc = DC; + rst = RST; + cs = CS; + hwSPI = true; +} + +// initializer for I2C - we only indicate the reset pin! +Adafruit_SSD1306::Adafruit_SSD1306(int8_t reset) : + Adafruit_GFX(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT) { + sclk = dc = cs = sid = -1; + rst = reset; +} + + +bool Adafruit_SSD1306::begin(uint8_t vccstate, uint8_t i2caddr, bool reset) { + _vccstate = vccstate; + _i2caddr = i2caddr; + + // set pin directions + if (sid != -1){ + pinMode(dc, OUTPUT); + pinMode(cs, OUTPUT); +#ifdef HAVE_PORTREG + csport = portOutputRegister(digitalPinToPort(cs)); + cspinmask = digitalPinToBitMask(cs); + dcport = portOutputRegister(digitalPinToPort(dc)); + dcpinmask = digitalPinToBitMask(dc); +#endif + if (!hwSPI){ + // set pins for software-SPI + pinMode(sid, OUTPUT); + pinMode(sclk, OUTPUT); +#ifdef HAVE_PORTREG + clkport = portOutputRegister(digitalPinToPort(sclk)); + clkpinmask = digitalPinToBitMask(sclk); + mosiport = portOutputRegister(digitalPinToPort(sid)); + mosipinmask = digitalPinToBitMask(sid); +#endif + } + if (hwSPI){ + SPI.begin(); +#ifdef SPI_HAS_TRANSACTION + SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); +#else + SPI.setClockDivider (4); +#endif + } + } + else + { + // I2C Init + Wire.begin(); +#ifdef __SAM3X8E__ + // Force 400 KHz I2C, rawr! (Uses pins 20, 21 for SDA, SCL) + TWI1->TWI_CWGR = 0; + TWI1->TWI_CWGR = ((VARIANT_MCK / (2 * 400000)) - 4) * 0x101; +#endif + } + if ((reset) && (rst >= 0)) { + // Setup reset pin direction (used by both SPI and I2C) + pinMode(rst, OUTPUT); + digitalWrite(rst, HIGH); + // VDD (3.3V) goes high at start, lets just chill for a ms + delay(1); + // bring reset low + digitalWrite(rst, LOW); + // wait 10ms + delay(10); + // bring out of reset + digitalWrite(rst, HIGH); + // turn on VCC (9V?) + } + + uint8_t ret; + // Init sequence + LOG("Sending LCD display off"); + ret=ssd1306_command(SSD1306_DISPLAYOFF); // 0xAE + LOG("Display off returned %d",ret); + if (ret != 0) + { + + return false; + } + ssd1306_command(SSD1306_SETDISPLAYCLOCKDIV); // 0xD5 + ssd1306_command(0x80); // the suggested ratio 0x80 + + ssd1306_command(SSD1306_SETMULTIPLEX); // 0xA8 + ssd1306_command(SSD1306_LCDHEIGHT - 1); + + ssd1306_command(SSD1306_SETDISPLAYOFFSET); // 0xD3 + ssd1306_command(0x0); // no offset + ssd1306_command(SSD1306_SETSTARTLINE | 0x0); // line #0 + ssd1306_command(SSD1306_CHARGEPUMP); // 0x8D + if (vccstate == SSD1306_EXTERNALVCC) + { ssd1306_command(0x10); } + else + { ssd1306_command(0x14); } + ssd1306_command(SSD1306_MEMORYMODE); // 0x20 + ssd1306_command(0x00); // 0x0 act like ks0108 + ssd1306_command(SSD1306_SEGREMAP | 0x1); + ssd1306_command(SSD1306_COMSCANDEC); + +#if defined SSD1306_128_32 + ssd1306_command(SSD1306_SETCOMPINS); // 0xDA + ssd1306_command(0x02); + ssd1306_command(SSD1306_SETCONTRAST); // 0x81 + ssd1306_command(0x8F); + +#elif defined SSD1306_128_64 + ssd1306_command(SSD1306_SETCOMPINS); // 0xDA + ssd1306_command(0x12); + ssd1306_command(SSD1306_SETCONTRAST); // 0x81 + if (vccstate == SSD1306_EXTERNALVCC) + { ssd1306_command(0x9F); } + else + { ssd1306_command(0xCF); } + +#elif defined SSD1306_96_16 + ssd1306_command(SSD1306_SETCOMPINS); // 0xDA + ssd1306_command(0x2); //ada x12 + ssd1306_command(SSD1306_SETCONTRAST); // 0x81 + if (vccstate == SSD1306_EXTERNALVCC) + { ssd1306_command(0x10); } + else + { ssd1306_command(0xAF); } + +#endif + + ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9 + if (vccstate == SSD1306_EXTERNALVCC) + { ssd1306_command(0x22); } + else + { ssd1306_command(0xF1); } + ssd1306_command(SSD1306_SETVCOMDETECT); // 0xDB + ssd1306_command(0x40); + ssd1306_command(SSD1306_DISPLAYALLON_RESUME); // 0xA4 + ssd1306_command(SSD1306_NORMALDISPLAY); // 0xA6 + + ssd1306_command(SSD1306_DEACTIVATE_SCROLL); + + ssd1306_command(SSD1306_DISPLAYON);//--turn on oled panel + return true; +} + + +void Adafruit_SSD1306::invertDisplay(uint8_t i) { + if (i) { + ssd1306_command(SSD1306_INVERTDISPLAY); + } else { + ssd1306_command(SSD1306_NORMALDISPLAY); + } +} + +// Errors: +// 0 : Success +// 1 : Data too long +// 2 : NACK on transmit of address +// 3 : NACK on transmit of data +// 4 : Other error +uint8_t Adafruit_SSD1306::ssd1306_command(uint8_t c) { + if (sid != -1) + { + // SPI +#ifdef HAVE_PORTREG + *csport |= cspinmask; + *dcport &= ~dcpinmask; + *csport &= ~cspinmask; +#else + digitalWrite(cs, HIGH); + digitalWrite(dc, LOW); + digitalWrite(cs, LOW); +#endif + fastSPIwrite(c); +#ifdef HAVE_PORTREG + *csport |= cspinmask; +#else + digitalWrite(cs, HIGH); +#endif + } + else + { + // I2C + uint8_t control = 0x00; // Co = 0, D/C = 0 + //LOG("wire begin"); + Wire.beginTransmission(_i2caddr); + //LOG("wire write"); + Wire.write(control); + //LOG("wire write c"); + Wire.write(c); + //LOG("wire end"); + Wire.endTransmission(); + //LOG("wire done"); + } +} + +// startscrollright +// Activate a right handed scroll for rows start through stop +// Hint, the display is 16 rows tall. To scroll the whole display, run: +// display.scrollright(0x00, 0x0F) +void Adafruit_SSD1306::startscrollright(uint8_t start, uint8_t stop){ + ssd1306_command(SSD1306_RIGHT_HORIZONTAL_SCROLL); + ssd1306_command(0X00); + ssd1306_command(start); + ssd1306_command(0X00); + ssd1306_command(stop); + ssd1306_command(0X00); + ssd1306_command(0XFF); + ssd1306_command(SSD1306_ACTIVATE_SCROLL); +} + +// startscrollleft +// Activate a right handed scroll for rows start through stop +// Hint, the display is 16 rows tall. To scroll the whole display, run: +// display.scrollright(0x00, 0x0F) +void Adafruit_SSD1306::startscrollleft(uint8_t start, uint8_t stop){ + ssd1306_command(SSD1306_LEFT_HORIZONTAL_SCROLL); + ssd1306_command(0X00); + ssd1306_command(start); + ssd1306_command(0X00); + ssd1306_command(stop); + ssd1306_command(0X00); + ssd1306_command(0XFF); + ssd1306_command(SSD1306_ACTIVATE_SCROLL); +} + +// startscrolldiagright +// Activate a diagonal scroll for rows start through stop +// Hint, the display is 16 rows tall. To scroll the whole display, run: +// display.scrollright(0x00, 0x0F) +void Adafruit_SSD1306::startscrolldiagright(uint8_t start, uint8_t stop){ + ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA); + ssd1306_command(0X00); + ssd1306_command(SSD1306_LCDHEIGHT); + ssd1306_command(SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL); + ssd1306_command(0X00); + ssd1306_command(start); + ssd1306_command(0X00); + ssd1306_command(stop); + ssd1306_command(0X01); + ssd1306_command(SSD1306_ACTIVATE_SCROLL); +} + +// startscrolldiagleft +// Activate a diagonal scroll for rows start through stop +// Hint, the display is 16 rows tall. To scroll the whole display, run: +// display.scrollright(0x00, 0x0F) +void Adafruit_SSD1306::startscrolldiagleft(uint8_t start, uint8_t stop){ + ssd1306_command(SSD1306_SET_VERTICAL_SCROLL_AREA); + ssd1306_command(0X00); + ssd1306_command(SSD1306_LCDHEIGHT); + ssd1306_command(SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL); + ssd1306_command(0X00); + ssd1306_command(start); + ssd1306_command(0X00); + ssd1306_command(stop); + ssd1306_command(0X01); + ssd1306_command(SSD1306_ACTIVATE_SCROLL); +} + +void Adafruit_SSD1306::stopscroll(void){ + ssd1306_command(SSD1306_DEACTIVATE_SCROLL); +} + +// Dim the display +// dim = true: display is dimmed +// dim = false: display is normal +void Adafruit_SSD1306::dim(boolean dim) { + uint8_t contrast; + + if (dim) { + contrast = 0; // Dimmed display + } else { + if (_vccstate == SSD1306_EXTERNALVCC) { + contrast = 0x9F; + } else { + contrast = 0xCF; + } + } + // the range of contrast to too small to be really useful + // it is useful to dim the display + ssd1306_command(SSD1306_SETCONTRAST); + ssd1306_command(contrast); +} + +void Adafruit_SSD1306::display(void) { + ssd1306_command(SSD1306_COLUMNADDR); + ssd1306_command(0); // Column start address (0 = reset) + ssd1306_command(SSD1306_LCDWIDTH-1); // Column end address (127 = reset) + + ssd1306_command(SSD1306_PAGEADDR); + ssd1306_command(0); // Page start address (0 = reset) +#if SSD1306_LCDHEIGHT == 64 + ssd1306_command(7); // Page end address +#endif +#if SSD1306_LCDHEIGHT == 32 + ssd1306_command(3); // Page end address +#endif +#if SSD1306_LCDHEIGHT == 16 + ssd1306_command(1); // Page end address +#endif + + if (sid != -1) + { + // SPI +#ifdef HAVE_PORTREG + *csport |= cspinmask; + *dcport |= dcpinmask; + *csport &= ~cspinmask; +#else + digitalWrite(cs, HIGH); + digitalWrite(dc, HIGH); + digitalWrite(cs, LOW); +#endif + + for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) { + fastSPIwrite(buffer[i]); + } +#ifdef HAVE_PORTREG + *csport |= cspinmask; +#else + digitalWrite(cs, HIGH); +#endif + } + else + { + // save I2C bitrate +#ifdef TWBR + uint8_t twbrbackup = TWBR; + TWBR = 12; // upgrade to 400KHz! +#endif + + //Serial.println(TWBR, DEC); + //Serial.println(TWSR & 0x3, DEC); + + // I2C + for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) { + // send a bunch of data in one xmission + Wire.beginTransmission(_i2caddr); + WIRE_WRITE(0x40); + for (uint8_t x=0; x<16; x++) { + WIRE_WRITE(buffer[i]); + i++; + } + i--; + Wire.endTransmission(); + } +#ifdef TWBR + TWBR = twbrbackup; +#endif + } +} + +// clear everything +void Adafruit_SSD1306::clearDisplay(void) { + memset(buffer, 0, (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8)); +} + + +inline void Adafruit_SSD1306::fastSPIwrite(uint8_t d) { + + if(hwSPI) { + (void)SPI.transfer(d); + } else { + for(uint8_t bit = 0x80; bit; bit >>= 1) { +#ifdef HAVE_PORTREG + *clkport &= ~clkpinmask; + if(d & bit) *mosiport |= mosipinmask; + else *mosiport &= ~mosipinmask; + *clkport |= clkpinmask; +#else + digitalWrite(sclk, LOW); + if(d & bit) digitalWrite(sid, HIGH); + else digitalWrite(sid, LOW); + digitalWrite(sclk, HIGH); +#endif + } + } +} + +void Adafruit_SSD1306::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) { + boolean bSwap = false; + switch(rotation) { + case 0: + // 0 degree rotation, do nothing + break; + case 1: + // 90 degree rotation, swap x & y for rotation, then invert x + bSwap = true; + ssd1306_swap(x, y); + x = WIDTH - x - 1; + break; + case 2: + // 180 degree rotation, invert x and y - then shift y around for height. + x = WIDTH - x - 1; + y = HEIGHT - y - 1; + x -= (w-1); + break; + case 3: + // 270 degree rotation, swap x & y for rotation, then invert y and adjust y for w (not to become h) + bSwap = true; + ssd1306_swap(x, y); + y = HEIGHT - y - 1; + y -= (w-1); + break; + } + + if(bSwap) { + drawFastVLineInternal(x, y, w, color); + } else { + drawFastHLineInternal(x, y, w, color); + } +} + +void Adafruit_SSD1306::drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) { + // Do bounds/limit checks + if(y < 0 || y >= HEIGHT) { return; } + + // make sure we don't try to draw below 0 + if(x < 0) { + w += x; + x = 0; + } + + // make sure we don't go off the edge of the display + if( (x + w) > WIDTH) { + w = (WIDTH - x); + } + + // if our width is now negative, punt + if(w <= 0) { return; } + + // set up the pointer for movement through the buffer + register uint8_t *pBuf = buffer; + // adjust the buffer pointer for the current row + pBuf += ((y/8) * SSD1306_LCDWIDTH); + // and offset x columns in + pBuf += x; + + register uint8_t mask = 1 << (y&7); + + switch (color) + { + case WHITE: while(w--) { *pBuf++ |= mask; }; break; + case BLACK: mask = ~mask; while(w--) { *pBuf++ &= mask; }; break; + case INVERSE: while(w--) { *pBuf++ ^= mask; }; break; + } +} + +void Adafruit_SSD1306::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) { + bool bSwap = false; + switch(rotation) { + case 0: + break; + case 1: + // 90 degree rotation, swap x & y for rotation, then invert x and adjust x for h (now to become w) + bSwap = true; + ssd1306_swap(x, y); + x = WIDTH - x - 1; + x -= (h-1); + break; + case 2: + // 180 degree rotation, invert x and y - then shift y around for height. + x = WIDTH - x - 1; + y = HEIGHT - y - 1; + y -= (h-1); + break; + case 3: + // 270 degree rotation, swap x & y for rotation, then invert y + bSwap = true; + ssd1306_swap(x, y); + y = HEIGHT - y - 1; + break; + } + + if(bSwap) { + drawFastHLineInternal(x, y, h, color); + } else { + drawFastVLineInternal(x, y, h, color); + } +} + + +void Adafruit_SSD1306::drawFastVLineInternal(int16_t x, int16_t __y, int16_t __h, uint16_t color) { + + // do nothing if we're off the left or right side of the screen + if(x < 0 || x >= WIDTH) { return; } + + // make sure we don't try to draw below 0 + if(__y < 0) { + // __y is negative, this will subtract enough from __h to account for __y being 0 + __h += __y; + __y = 0; + + } + + // make sure we don't go past the height of the display + if( (__y + __h) > HEIGHT) { + __h = (HEIGHT - __y); + } + + // if our height is now negative, punt + if(__h <= 0) { + return; + } + + // this display doesn't need ints for coordinates, use local byte registers for faster juggling + register uint8_t y = __y; + register uint8_t h = __h; + + + // set up the pointer for fast movement through the buffer + register uint8_t *pBuf = buffer; + // adjust the buffer pointer for the current row + pBuf += ((y/8) * SSD1306_LCDWIDTH); + // and offset x columns in + pBuf += x; + + // do the first partial byte, if necessary - this requires some masking + register uint8_t mod = (y&7); + if(mod) { + // mask off the high n bits we want to set + mod = 8-mod; + + // note - lookup table results in a nearly 10% performance improvement in fill* functions + // register uint8_t mask = ~(0xFF >> (mod)); + static uint8_t premask[8] = {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE }; + register uint8_t mask = premask[mod]; + + // adjust the mask if we're not going to reach the end of this byte + if( h < mod) { + mask &= (0XFF >> (mod-h)); + } + + switch (color) + { + case WHITE: *pBuf |= mask; break; + case BLACK: *pBuf &= ~mask; break; + case INVERSE: *pBuf ^= mask; break; + } + + // fast exit if we're done here! + if(h= 8) { + if (color == INVERSE) { // separate copy of the code so we don't impact performance of the black/white write version with an extra comparison per loop + do { + *pBuf=~(*pBuf); + + // adjust the buffer forward 8 rows worth of data + pBuf += SSD1306_LCDWIDTH; + + // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now) + h -= 8; + } while(h >= 8); + } + else { + // store a local value to work with + register uint8_t val = (color == WHITE) ? 255 : 0; + + do { + // write our value in + *pBuf = val; + + // adjust the buffer forward 8 rows worth of data + pBuf += SSD1306_LCDWIDTH; + + // adjust h & y (there's got to be a faster way for me to do this, but this should still help a fair bit for now) + h -= 8; + } while(h >= 8); + } + } + + // now do the final partial byte, if necessary + if(h) { + mod = h & 7; + // this time we want to mask the low bits of the byte, vs the high bits we did above + // register uint8_t mask = (1 << mod) - 1; + // note - lookup table results in a nearly 10% performance improvement in fill* functions + static uint8_t postmask[8] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F }; + register uint8_t mask = postmask[mod]; + switch (color) + { + case WHITE: *pBuf |= mask; break; + case BLACK: *pBuf &= ~mask; break; + case INVERSE: *pBuf ^= mask; break; + } + } +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.h b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.h new file mode 100644 index 0000000..7d7a5fe --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.h @@ -0,0 +1,182 @@ +/********************************************************************* +This is a library for our Monochrome OLEDs based on SSD1306 drivers + + Pick one up today in the adafruit shop! + ------> http://www.adafruit.com/category/63_98 + +These displays use SPI to communicate, 4 or 5 pins are required to +interface + +Adafruit invests time and resources providing this open source code, +please support Adafruit and open-source hardware by purchasing +products from Adafruit! + +Written by Limor Fried/Ladyada for Adafruit Industries. +BSD license, check license.txt for more information +All text above, and the splash screen must be included in any redistribution +*********************************************************************/ +#ifndef _Adafruit_SSD1306_H_ +#define _Adafruit_SSD1306_H_ + +#if ARDUINO >= 100 + #include "Arduino.h" + #define WIRE_WRITE Wire.write +#else + #include "WProgram.h" + #define WIRE_WRITE Wire.send +#endif + +#if defined(__SAM3X8E__) + typedef volatile RwReg PortReg; + typedef uint32_t PortMask; + #define HAVE_PORTREG +#elif defined(ARDUINO_ARCH_SAMD) +// not supported +#elif defined(ESP8266) || defined(ARDUINO_STM32_FEATHER) + typedef volatile uint32_t PortReg; + typedef uint32_t PortMask; +#else + typedef volatile uint8_t PortReg; + typedef uint8_t PortMask; + #define HAVE_PORTREG +#endif + +#include +#include "Adafruit_GFX.h" + +#define BLACK 0 +#define WHITE 1 +#define INVERSE 2 + +#define SSD1306_I2C_ADDRESS 0x3C // 011110+SA0+RW - 0x3C or 0x3D +// Address for 128x32 is 0x3C +// Address for 128x64 is 0x3D (default) or 0x3C (if SA0 is grounded) + +/*========================================================================= + SSD1306 Displays + ----------------------------------------------------------------------- + The driver is used in multiple displays (128x64, 128x32, etc.). + Select the appropriate display below to create an appropriately + sized framebuffer, etc. + + SSD1306_128_64 128x64 pixel display + + SSD1306_128_32 128x32 pixel display + + SSD1306_96_16 + + -----------------------------------------------------------------------*/ + #define SSD1306_128_64 +// #define SSD1306_128_32 +// #define SSD1306_96_16 +/*=========================================================================*/ + +#if defined SSD1306_128_64 && defined SSD1306_128_32 + #error "Only one SSD1306 display can be specified at once in SSD1306.h" +#endif +#if !defined SSD1306_128_64 && !defined SSD1306_128_32 && !defined SSD1306_96_16 + #error "At least one SSD1306 display must be specified in SSD1306.h" +#endif + +#if defined SSD1306_128_64 + #define SSD1306_LCDWIDTH 128 + #define SSD1306_LCDHEIGHT 64 +#endif +#if defined SSD1306_128_32 + #define SSD1306_LCDWIDTH 128 + #define SSD1306_LCDHEIGHT 32 +#endif +#if defined SSD1306_96_16 + #define SSD1306_LCDWIDTH 96 + #define SSD1306_LCDHEIGHT 16 +#endif + +#define SSD1306_SETCONTRAST 0x81 +#define SSD1306_DISPLAYALLON_RESUME 0xA4 +#define SSD1306_DISPLAYALLON 0xA5 +#define SSD1306_NORMALDISPLAY 0xA6 +#define SSD1306_INVERTDISPLAY 0xA7 +#define SSD1306_DISPLAYOFF 0xAE +#define SSD1306_DISPLAYON 0xAF + +#define SSD1306_SETDISPLAYOFFSET 0xD3 +#define SSD1306_SETCOMPINS 0xDA + +#define SSD1306_SETVCOMDETECT 0xDB + +#define SSD1306_SETDISPLAYCLOCKDIV 0xD5 +#define SSD1306_SETPRECHARGE 0xD9 + +#define SSD1306_SETMULTIPLEX 0xA8 + +#define SSD1306_SETLOWCOLUMN 0x00 +#define SSD1306_SETHIGHCOLUMN 0x10 + +#define SSD1306_SETSTARTLINE 0x40 + +#define SSD1306_MEMORYMODE 0x20 +#define SSD1306_COLUMNADDR 0x21 +#define SSD1306_PAGEADDR 0x22 + +#define SSD1306_COMSCANINC 0xC0 +#define SSD1306_COMSCANDEC 0xC8 + +#define SSD1306_SEGREMAP 0xA0 + +#define SSD1306_CHARGEPUMP 0x8D + +#define SSD1306_EXTERNALVCC 0x1 +#define SSD1306_SWITCHCAPVCC 0x2 + +// Scrolling #defines +#define SSD1306_ACTIVATE_SCROLL 0x2F +#define SSD1306_DEACTIVATE_SCROLL 0x2E +#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 +#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 +#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 +#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 +#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A + +class Adafruit_SSD1306 : public Adafruit_GFX { + public: + Adafruit_SSD1306(int8_t SID, int8_t SCLK, int8_t DC, int8_t RST, int8_t CS); + Adafruit_SSD1306(int8_t DC, int8_t RST, int8_t CS); + Adafruit_SSD1306(int8_t RST = -1); + + bool begin(uint8_t switchvcc = SSD1306_SWITCHCAPVCC, uint8_t i2caddr = SSD1306_I2C_ADDRESS, bool reset=true); + uint8_t ssd1306_command(uint8_t c); + + void clearDisplay(void); + void invertDisplay(uint8_t i); + void display(); + + void startscrollright(uint8_t start, uint8_t stop); + void startscrollleft(uint8_t start, uint8_t stop); + + void startscrolldiagright(uint8_t start, uint8_t stop); + void startscrolldiagleft(uint8_t start, uint8_t stop); + void stopscroll(void); + + void dim(boolean dim); + + void drawPixel(int16_t x, int16_t y, uint16_t color); + + virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); + virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); + + private: + int8_t _i2caddr, _vccstate, sid, sclk, dc, rst, cs; + void fastSPIwrite(uint8_t c); + + boolean hwSPI; +#ifdef HAVE_PORTREG + PortReg *mosiport, *clkport, *csport, *dcport; + PortMask mosipinmask, clkpinmask, cspinmask, dcpinmask; +#endif + + inline void drawFastVLineInternal(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline)); + inline void drawFastHLineInternal(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline)); + +}; + +#endif /* _Adafruit_SSD1306_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.cpp new file mode 100644 index 0000000..2604732 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.cpp @@ -0,0 +1,192 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "Flash.h" +#include "syslog.h" + +bool flashInit(void){ + if (NVMCTRL->PARAM.bit.PSZ != 3) + { + ERROR("FLASH PAGE SIZE is not 64 bytes"); + return false; + } + return true; +} + + +static void erase(const volatile void *flash_ptr) +{ + NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2; + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER; + while (!NVMCTRL->INTFLAG.bit.READY) { } +} + +bool flashErase(const volatile void *flash_ptr, uint32_t size) +{ + const uint8_t *ptr = (const uint8_t *)flash_ptr; + while (size > FLASH_ROW_SIZE) { + erase(ptr); + ptr += FLASH_ROW_SIZE; + size -= FLASH_ROW_SIZE; + } + if (size>0) + { + erase(ptr); + } + return true; //TODO should verify the erase +} + +static inline uint32_t read_unaligned_uint32(const void *data) +{ + union { + uint32_t u32; + uint8_t u8[4]; + } res; + const uint8_t *d = (const uint8_t *)data; + res.u8[0] = d[0]; + res.u8[1] = d[1]; + res.u8[2] = d[2]; + res.u8[3] = d[3]; + return res.u32; +} + + +void flashWrite(const volatile void *flash_ptr,const void *data, uint32_t size) +{ + uint32_t *ptrPage; + uint8_t *destPtr; + uint8_t *srcPtr; + uint32_t bytesInBlock; + __attribute__((__aligned__(4))) uint8_t buffer[FLASH_ROW_SIZE]; + uint32_t offset; + + destPtr=(uint8_t *)flash_ptr; + srcPtr=(uint8_t *)data; + + //LOG("flash write called"); + while(size>0) + { + uint32_t i,j; + + //calculate the maximum number of bytes we can write in page + offset=((uint32_t)destPtr)%(FLASH_ROW_SIZE); //offset into page + bytesInBlock=FLASH_ROW_SIZE-offset; //this is how many bytes we need to overwrite in this page + + //LOG("offset %d, bytesInBlock %d size %d", offset, bytesInBlock,size); + //get pointer to start of page + ptrPage=(uint32_t *) ((((uint32_t)destPtr)/(FLASH_ROW_SIZE)) * FLASH_ROW_SIZE); + + //LOG("pointer to page %d(0x%08x) %d",(uint32_t)ptrPage,(uint32_t)ptrPage,destPtr); + + //fill page buffer with data from flash + memcpy(buffer,ptrPage,FLASH_ROW_SIZE); + + //now fill buffer with new data that needs changing + i=bytesInBlock; + if (sizeCTRLB.bit.MANW = 1; + + // Do writes in pages + while (size) + { + // Execute "PBC" Page Buffer Clear + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC; + while (NVMCTRL->INTFLAG.bit.READY == 0) { } + + // Fill page buffer + uint32_t i; + for (i=0; i<(FLASH_PAGE_SIZE/4) && size; i++) //we write 4 bytes at a time + { + *dst_addr = read_unaligned_uint32(src_addr); + src_addr += 4; + dst_addr++; + size--; //size is set to number of 32bit words in first line above + } + + // Execute "WP" Write Page + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP; + while (NVMCTRL->INTFLAG.bit.READY == 0) { } + } + + +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.h b/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.h new file mode 100644 index 0000000..c95d700 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.h @@ -0,0 +1,68 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __FLASH__H__ +#define __FLASH__H__ + +#include +#include "syslog.h" + + +#define FLASH_PAGE_SIZE_NZS (64) //bytes +#define FLASH_ROW_SIZE (FLASH_PAGE_SIZE_NZS*4) //defined in the datasheet as 4x page size +#define FLASH_ERASE_VALUE (0xFF) //value of flash after an erase + +#define FLASH_ALLOCATE(name, size) \ + __attribute__((__aligned__(FLASH_ROW_SIZE))) \ + const uint8_t name[(size+(FLASH_ROW_SIZE-1))/FLASH_ROW_SIZE*FLASH_ROW_SIZE] = { }; + +bool flashInit(void); //this checks that our assumptions are true + +bool flashErase(const volatile void *flash_ptr, uint32_t size); +void flashWrite(const volatile void *flash_ptr,const void *data,uint32_t size); +void flashWritePage(const volatile void *flash_ptr, const void *data, uint32_t size); + +//you can read by dereferencing pointer but we will add a read +static inline int32_t flashRead(const volatile void *flash_ptr, void *data, uint32_t size) +{ + memcpy(data, (const void *)flash_ptr, size); +} + + + + +#endif //__FLASH__H__ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/angle.h b/firmware_smartstepper_trikarus/stepper_nano_zero/angle.h new file mode 100644 index 0000000..34e0226 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/angle.h @@ -0,0 +1,147 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#ifndef ANGLE_H_ +#define ANGLE_H_ +#include +#include +#include + +#define ANGLE_STEPS (0x010000UL) +#define ANGLE_MAX ((uint16_t)0x0FFFF) + +#define ANGLE_FROM_DEGREES(x) ((int32_t) ( ((float)ANGLE_STEPS*(float)(x)+180.0)/360.0 ) ) +#define ANGLE_T0_DEGREES(x) ( (float) ((float(x)*360.0)/((float)ANGLE_STEPS) )) +class Angle +{ +private: + uint16_t angle; +public: + Angle(void) {angle=0;} + Angle(int32_t x) {angle=(uint16_t)x;} + Angle(const Angle &x) {angle=x.angle;} + + int16_t operator-( const Angle &a2) + { + int32_t x,y,dx; + x=(int32_t)angle; + y=(int32_t)a2.angle; + dx=x-y; + if (abs(x-y)>ANGLE_STEPS/2) + { + //we have a wrap condition + if (x>y) + { + dx=x-(y+ANGLE_STEPS); + }else if (xANGLE_MAX) +// { +// y=y-ANGLE_STEPS; +// } +// while(y<-ANGLE_MAX) +// { +// y=y+ANGLE_STEPS; +// } +// +// dx=x-y; +// if (abs(x-y)>ANGLE_STEPS/2) +// { +// //we have a wrap condition +// if (x>y) +// { +// dx=x-(y+ANGLE_STEPS); +// }else if (x=ANGLE_STEPS) + { + a=a-ANGLE_STEPS; + } + while (a<0) + { + a=a+ANGLE_STEPS; + } + return Angle((uint16_t)a); + } + Angle operator+(const unsigned long int x) + { + uint32_t a; + a=(uint32_t)angle+ x; + while (a>=ANGLE_STEPS) + { + a=a-ANGLE_STEPS; + } + return Angle((uint16_t)a); + } + + operator uint16_t() const {return angle;} + operator uint32_t() const {return (uint32_t)angle;} + operator int32_t() const {return (int32_t)angle;} + + + +}; + + +#endif /* ANGLE_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.cpp new file mode 100644 index 0000000..0812c36 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.cpp @@ -0,0 +1,322 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include +#include "syslog.h" +#include "as5047d.h" +#include "SPI.h" +#include +#include "board.h" + +#define AS5047D_CMD_NOP (0x0000) +#define AS5047D_CMD_ERRFL (0x0001) +#define AS5047D_CMD_PROG (0x0003) +#define AS5047D_CMD_DIAAGC (0x3FFC) +#define AS5047D_CMD_MAG (0x3FFD) +#define AS5047D_CMD_ANGLEUNC (0x3FFE) +#define AS5047D_CMD_ANGLECOM (0x3FFF) + + +#define AS5048A_CMD_NOP (0x0000) +#define AS5048A_CMD_ERRFL (0x0001) +#define AS5048A_CMD_PROG (0x0003) +#define AS5048A_CMD_DIAAGC (0x3FFD) +#define AS5048A_CMD_MAG (0x3FFE) +#define AS5048A_CMD_ANGLE (0x3FFF) + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + +static int getBit(int16_t data, int bit) +{ + return (data>>bit) & 0x01; +} + +static int getParity(uint16_t data) +{ + int i,bits; + data=data & 0x7FFF; //mask out upper bit + + //count number of bits, brute force + bits=0; + for(i=0; i<16; i++) + { + if (0 != (data & ((0x0001)<0) + { + delay(1); + t0--; + if (t0==0) + { + ERROR("LF bit not set"); + error=true; + break; + //return false; + } + LOG("AS5047D diag data is 0x%04X",data); + data=readAddress(AS5047D_CMD_DIAAGC); + } + + if (error) + { + error=false; + uint16_t data=0,t0=100; + while (getBit(data,8)==0 && t0>0) + { + delay(1); + t0--; + if (t0==0) + { + ERROR("AS5048A OCF bit not set"); + error=true; + return false; + } + data=readAddress(AS5048A_CMD_DIAAGC); + LOG("AS5048A diag data is 0x%04X",data); + } + as5047d=false; + + } + + +#ifdef NZS_AS5047_PIPELINE + //read encoder a few times to flush the pipeline + readEncoderAnglePipeLineRead(); + readEncoderAnglePipeLineRead(); +#endif + return true; +} + + +//read the encoders +int16_t AS5047D::readAddress(uint16_t addr) +{ + uint16_t data; + error=false; + //make sure it is a read by setting bit 14 + addr=addr | 0x4000; + + //add the parity to the command + if (1 == getParity(addr)) + { + addr=(addr & 0x7FFF) | 0x8000; //add parity bit to make command even number of bits + } + + digitalWrite(chipSelectPin, LOW); + delayMicroseconds(1); + //clock out the address to read + SPI.transfer16(addr); + digitalWrite(chipSelectPin, HIGH); + delayMicroseconds(1); + digitalWrite(chipSelectPin, LOW); + //clock out zeros to read in the data from address + data=SPI.transfer16(0x00); + + digitalWrite(chipSelectPin, HIGH); + + if (data & (1<<14)) + { + //if bit 14 is set then we have an error + ERROR("read command 0x%04X failed",addr); + error=true; + return -1; + } + + if (data>>15 != getParity(data)) + { + //parity did not match + ERROR("read command parity error 0x%04X ",addr); + error=true; + return -2; + } + + data=data & 0x3FFF; //mask off the error and parity bits + + return data; +} + +//read the encoders +int16_t AS5047D::readEncoderAngle(void) +{ + if (as5047d) + { + return readAddress(AS5047D_CMD_ANGLECOM); + } + return readAddress(AS5048A_CMD_ANGLE); +} + +//pipelined read of the encoder angle used for high speed reads, but value is always one read behind +int16_t AS5047D::readEncoderAnglePipeLineRead(void) +{ + + int16_t data; + int error, t0=10; + GPIO_LOW(chipSelectPin);//(chipSelectPin, LOW); + //delayMicroseconds(1); + do { + + // doing two 8 bit transfers is faster than one 16 bit + data =(uint16_t)SPI.transfer(0xFF)<<8 | ((uint16_t)SPI.transfer(0xFF) & 0x0FF); + t0--; + if (t0<=0) + { + ERROR("AS5047D problem"); + break; + } + //data=SPI.transfer16(0xFFFF); //to speed things up we know the parity and address for the read + }while(data & (1<<14)); //while error bit is set + + data=data & 0x3FFF; //mask off the error and parity bits + GPIO_HIGH(chipSelectPin); + //digitalWrite(chipSelectPin, HIGH); + //TODO we really should check for errors and return a negative result or something + return data; +} + + +void AS5047D::diagnostics(char *ptrStr) +{ + int16_t data; + int m,d; + + if (as5047d) + { + + data=readAddress(AS5047D_CMD_DIAAGC); + + if (NULL == ptrStr) + { + LOG("DIAAGC: 0x%04X", data); + LOG("MAGL: %d", getBit(data,11)); + LOG("MAGH: %d", getBit(data,10)); + LOG("COF: %d", getBit(data,9)); + LOG("LFGL: %d", getBit(data,8)); + LOG("AGC: %d", data & 0x0FF); + + data=readAddress(AS5047D_CMD_MAG); + LOG("CMAG: 0x%04X(%d)",data,data); + + data=readAddress(AS5047D_CMD_ANGLEUNC); + m=(int)((float)data*AS5047D_DEGREES_PER_BIT); + d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); + LOG("CORDICANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d); + + data=readAddress(AS5047D_CMD_ANGLECOM); + m=(int)((float)data*AS5047D_DEGREES_PER_BIT); + d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); + LOG("DAECANG: 0x%04X(%d) %d.%02d deg(est)",data,data,m,d); + }else + { + sprintf(ptrStr,"DIAAGC: 0x%04X\n\r", data); + sprintf(ptrStr,"%sMAGL: %d\n\r", ptrStr,getBit(data,11)); + sprintf(ptrStr,"%sMAGH: %d\n\r", ptrStr,getBit(data,10)); + sprintf(ptrStr,"%sCOF: %d\n\r", ptrStr, getBit(data,9)); + sprintf(ptrStr,"%sLFGL: %d\n\r", ptrStr, getBit(data,8)); + sprintf(ptrStr,"%sAGC: %d\n\r", ptrStr,data & 0x0FF); + + data=readAddress(AS5047D_CMD_MAG); + sprintf(ptrStr,"%sCMAG: 0x%04X(%d)\n\r", ptrStr,data,data); + + data=readAddress(AS5047D_CMD_ANGLEUNC); + m=(int)((float)data*AS5047D_DEGREES_PER_BIT); + d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); + sprintf(ptrStr,"%sCORDICANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d); + + data=readAddress(AS5047D_CMD_ANGLECOM); + m=(int)((float)data*AS5047D_DEGREES_PER_BIT); + d=(int)((float)data*AS5047D_DEGREES_PER_BIT*100 -m*100); + sprintf(ptrStr,"%sDAECANG: 0x%04X(%d) %d.%02d deg(est)\n\r", ptrStr,data,data,m,d); + + } + } else + { + data=readAddress(AS5048A_CMD_DIAAGC); + sprintf(ptrStr,"AS5048A DIAAGC: 0x%04X\n\r", data); + data=readAddress(AS5048A_CMD_MAG); + sprintf(ptrStr,"%sMagnitude: %d\n\r", ptrStr,data); + data=readAddress(AS5048A_CMD_ANGLE); + sprintf(ptrStr,"%sAngle: %d\n\r", ptrStr,data); + } + +} + +#pragma GCC pop_options + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.h b/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.h new file mode 100644 index 0000000..8252c93 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.h @@ -0,0 +1,58 @@ +/********************************************************************** + Copyright (C) 2019 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __AS5047D_H__ +#define __AS5047D_H__ + +#include +#define AS5047D_DEGREES_PER_BIT (360.0/(float)(0x3FFF)) + +class AS5047D { + private: + int chipSelectPin; + int16_t readAddress(uint16_t addr); + bool error=false; + bool as5047d=true; + public: + boolean begin(int csPin); + int16_t readEncoderAngle(void); + void diagnostics(char *ptrStr); + int16_t readEncoderAnglePipeLineRead(void); + bool getError(void) {return error;}; +}; + +#endif //__AS5047D_H__ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/board.h b/firmware_smartstepper_trikarus/stepper_nano_zero/board.h new file mode 100644 index 0000000..cd7a87d --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/board.h @@ -0,0 +1,564 @@ +/********************************************************************** +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include + + +//uncomment this if you are using the Mechaduino hardware +//#define MECHADUINO_HARDWARE + + +//uncomment the follow lines if using the NEMA 23 10A hardware +//#define NEMA_23_10A_HW + +//uncomment the following if the board uses the A5995 driver (NEMA 23 3.2A boards) +//#define A5995_DRIVER + +//The March 21 2017 NEMA 17 Smart Stepper has changed some pin outs +// A1 was changed to read motor voltage, hence SW4 is now using D4 +// comment out this next line if using the older hardware +#define NEMA17_SMART_STEPPER_3_21_2017 + +#if defined(MECHADUINO_HARDWARE) && defined(NEMA17_SMART_STEPPER_3_21_2017) +#error "Cannot have both MECHADUINO_HARDWARE and NEMA17_SMART_STEPPER_3_21_2017 defined in board.h" +#endif + +//The MKS Servo42 uses the A1333_Encoder +// Please uncomment this line and make sure the NEMA17_SMART_STEPPER_3_21_2017 is +// uncommented for the Servo42 +//#define A1333_ENCODER + +#ifdef A5995_DRIVER +#ifdef NEMA17_SMART_STEPPER_3_21_2017 +#error "Only NEMA17_SMART_STEPPER_3_21_2017 or A5595_DRIVER may be defined" +#endif +#endif + +#define NZS_FAST_CAL // define this to use 32k of flash for fast calibration table +#define NZS_FAST_SINE //uses 2048 extra bytes to implement faster sine tables + + +#define NZS_AS5047_PIPELINE //does a pipeline read of encoder, which is slightly faster + +#define NZS_CONTROL_LOOP_HZ (6000) //update rate of control loop + + +#define NZS_LCD_ABSOULTE_ANGLE //define this to show angle from zero in positive and negative direction +// for example 2 rotations from start will be angle of 720 degrees + +//#define ENABLE_PHASE_PREDICTION //this enables prediction of phase at high velocity to increase motor speed +//as of FW0.11 it is considered development only + +#define VERSION "FW: 0.40" //this is what prints on LCD during splash screen + +//Define this to allow command out serial port, else hardware serial is debug log +//#define CMD_SERIAL_PORT + +#define SERIAL_BAUD (115200) //baud rate for the serial ports + +//This section is for using the step and dir pins as serial port +// when the enable pin is inactive. +#ifndef MECHADUINO_HARDWARE +#define USE_STEP_DIR_SERIAL +#define STEP_DIR_BAUD (19200) //this is the baud rate we will use +#endif + + +// These are used as an attempt to use TC4 to count steps +// currently this is not working. +//#define USE_NEW_STEP //define this to use new step method +#define USE_TC_STEP //use timer counter for step pin + +#ifndef F_CPU +#define F_CPU (48000000UL) +#endif + +/* TODO are flaged with TODO + * TODO - add detection of magnet to make sure PCB is on motor + */ + +/* change log + * 0.02 added fixes for 0.9 degree motor + * 0.03 added code for using error pin as an enable pin, enable feedback by default + * 0.04 + * 0.05 added different modes added support for mechaduino + * 0.06 added time out pipeline read, add some error logging on encoder failure for mechaduino + * 0.07 many changes including + * - fixed error on display when doing a move 99999 + * - added velocity and position PID modes + * - fixed LCD menu and put LCD code in own file + * - include LCD source files from adafruit as that ssd1306 need lcd resoultion fix + * - added motor parameters to NVM such step size and rotation are only check on first boot + * - added test on power up to see if motor power is applied. + * - added factory reset command + * - pPID is not stable in my testing. + * 0.08 + * - moved enable pin processing out of interrupt context + * - added mode for inverted logic on the enable pin + * - added pin definitions for NEMA23 10A hardware + * - Changed enable such that it does not move motor but just sets current posistion + * 0.09 + * - enabled auto detection of LCD + * - cleaned up the commands, made motorparams and systemparams individual commands + * - added the option to the move command to move at a constant RPM + * - Added the setzero command to zero the relative location of motor + * - Added the stop command to stop the planner based moves. + * 0.10 + * -Fixed bug in switching control mode to 3 + * 0.11 + * - Fixed bug where output current was half of what it should have been (sine.h) + * - Added #define for phase predictive advancement + * - Changed calibration to be done with one coil/phase on + * - Added smoothing for calibration + * - Continue to work on the Fet Driver code. + * 0.12 + * - Continue to work on the FET driver code + * - fixed a constant issue with the DAC for the A4954 driver + * - added command for setting the operational mode of the enable pin + * - added the start of the A5995 driver. + * 0.13 + * - Added delay in for the 0.9 degree motor calibration and testing + * - changed calibration to move 1/2 step at time as it was causing problems on A5995 due to current ramp down + * 0.14 - Added in data logging + * - Averaged the encoder when the motor is stationary to reduce noise/vibrations + * 0.15 - Fixed some fet driver code + * - Added support for the NEMA17 smart stepper + * - Fixed RPM display bug on the LCD + * 0.16 - Added support for enable and error pins on the 3-21-2017 hardware + * + * 0.17 - Added the ability for the command line to go over the hardwired serial port + * - Fixed a bug where step and direction pin were setup as pulled down pins + * which could cause false stepping in nosiey environments + * 0.18 - Added support for EEPROM writting of last location during brown out - currently brown out is too fast to write + * - Added commands to support reading and restoring location from eeprom + * - Check for pull up on SDA/SCL before doing a I2C read as that SERCOM driver has not time outs and locks. + * - Added faster detection of USB not being plugged in, reduces power up time with no USB + * 0.19 - removed debug information in the ssd1306 driver which caused LCD not always to be found + * 0.20 - Fixed bug in calibration, thanks to Oliver E. + * 0.21 - Fixed issues compiling for mechaduino, including disabling LCD for MEchaduino + * 0.22 - Added home command; + * 0.23 -- added motor voltage sense to remove stepping on power up + * 0.24 - Disabled the home command which used the enable pin if you do not have enable pin + * 0.25 - Added pin read command + * 0.26 - changed the step/dir pins to be input_pullups + * 0.27 - added the option to make the step/dir uart when enable is low. + * - fixed enable to line to disable the A4954 driver + * 0.28 - Enabled some homing options (still under development) + * 0.29 - fixed rounding bug in ANGLE_T0_DEGREES + * 0.30 - Added support for the AS5048A encoder + * 0.31 - Added reading enable pin on during main loop + * 0.32 - Fixed issue where steps were not being counted correctly + * 0.33 - changed sPID parameters back to 0.9 0.0001 0.01 + * 0.34 - Added board type to the splash screen + * 0.35 - fixed usign TC4 (USE_TC_STEP) for counting steps. We can measure steps + * - at over 125khz, however the dir pin has ~8us setup time due to interrupt latency. + * - Added debug command to allow debug messages out the USB serial port + * 0.36 - eeprom set location math was wrong. + * 0.37 - fixed bug where the motor would pause periodically do the the TC4 counter. + * 0.38 - fixed bug in the velocity feedback mode. + * 0.39 - changed step count to TCC2, improved the dir pin setup/hold times + * - added support for the MKS Servo42 (A1333 encoder) + * 0.40 - fixed compiling errors for Mechaduino. Added sanity checks for different hardware boards (AK) + */ + + +/* + * Typedefs that are used across multiple files/modules + */ +typedef enum { + CW_ROTATION=0, + CCW_ROTATION=1, +} RotationDir_t; + +typedef enum { + ERROR_PIN_MODE_ENABLE=0, //error pin works like enable on step sticks + ERROR_PIN_MODE_ACTIVE_LOW_ENABLE=1, //error pin works like enable on step sticks + ERROR_PIN_MODE_ERROR=2, //error pin is low when there is angle error + ERROR_PIN_MODE_BIDIR=3, //error pin is bidirection open collector + +} ErrorPinMode_t; + +typedef enum { + CTRL_OFF =0, //controller is disabled + CTRL_OPEN=1, //controller is in open loop mode + CTRL_SIMPLE = 2, //simple error controller + CTRL_POS_PID =3, //PID Position controller + CTRL_POS_VELOCITY_PID =4, //PID Velocity controller + CTRL_TORQUE =5 +} feedbackCtrl_t; + +// ******** EVENT SYS USAGAE ************ +// Channel 0 - Step pin event + +// ******** TIMER USAGE A4954 versions ************ +//TCC1 is used for DAC PWM to the A4954 +//TCC0 can be used as PWM for the input pins on the A4954 +//TCC2 is used for the step count +//D0 step input could use TCC1 or TCC0 if not used +//TC3 is used for planner tick +//TC5 is use for timing the control loop + +// ******** TIMER USAGE NEMA23 10A versions ************ +//TCC0 PWM for the FET IN pins +//D10 step input could use TC3 or TCC0 if not used +//TC3 is used for planner tick +//TC4 is used for step count +//TC5 is use for timing the control loop + + +//mechaduio and Arduino Zero has defined serial ports differently than NZS +#ifdef MECHADUINO_HARDWARE +#warning "Compiling source for Mechaduino NOT NZS" +#define DISABLE_LCD +#undef Serial5 +#define Serial5 Serial +#else +#define SerialUSB Serial +#endif + +#define PIN_TXD (30) +#define PIN_RXD (31) + +#define PIN_STEP_INPUT (0) +#define PIN_DIR_INPUT (1) + +#define PIN_MOSI (23) +#define PIN_SCK (24) +#define PIN_MISO (22) + +#ifdef MECHADUINO_HARDWARE +#ifdef USE_STEP_DIR_SERIAL +#error "Step/Dir UART not supported on Mechaduino yet" +#endif + +#define PIN_ERROR (19) //analogInputToDigitalPin(PIN_A5)) +#else //not Mechaduino hardware +#ifdef NEMA17_SMART_STEPPER_3_21_2017 +#define PIN_SW1 (19)//analogInputToDigitalPin(PIN_A5)) +#define PIN_SW3 (14)//analogInputToDigitalPin(PIN_A0)) + +#ifdef A1333_ENCODER //the MKS Servo42 uses A1 for this switch +#define PIN_SW4 (15)//analogInputToDigitalPin(PIN_A1)) +#else +#define PIN_SW4 (2)//D2 +#endif + +#define PIN_ENABLE (10) +#define PIN_ERROR (3) + +#define PIN_VMOTOR (A1) //analog pin for the motor + +#else +#define PIN_SW1 (19)//analogInputToDigitalPin(PIN_A5)) +#define PIN_SW3 (14)//analogInputToDigitalPin(PIN_A0)) +#define PIN_SW4 (15)//analogInputToDigitalPin(PIN_A1)) +#define PIN_ERROR (10) +#endif + +#endif + +#ifdef A5995_DRIVER +#define PIN_ENABLE (3) +#endif + +#define PIN_SCL (21) +#define PIN_SDA (20) +#define PIN_USB_PWR (38) // this pin is high when usb is connected + +#define PIN_AS5047D_CS (16)//analogInputToDigitalPin(PIN_A2)) +#ifndef MECHADUINO_HARDWARE +#define PIN_AS5047D_PWR (11) //pull low to power on AS5047D +#endif + +//these pins use the TIMER in the A4954 driver +// changing the pin definitions here may require changes in the A4954.cpp file + +#define PIN_FET_IN1 (5) //PA15 TC3/WO[1] TCC0/WO[5]1 +#define PIN_FET_IN2 (6) //PA20 TC7/W0[0] TCC0/WO[6]2 +#define PIN_FET_IN3 (7) //PA21 TC7/WO[1] TCC0/WO[7]3 +#define PIN_FET_IN4 (2) //PA14 TC3/W0[0] TCC0/WO[4] 0 +#define PIN_FET_VREF1 (4) +#define PIN_FET_VREF2 (3) +#define PIN_FET_ENABLE (12) +//current sense pin from each H-bridge +#define ISENSE_FET_A (17) //analogInputToDigitalPin(PIN_A3) +#define ISENSE_FET_B (8) +//Comparators analog inputs +//#define COMP_FET_A (18)//analogInputToDigitalPin(PIN_A4)) +//#define COMP_FET_B (9) + + +//these are the pins used on the A5995 driver +#define PIN_A5995_ENABLE1 (2) //PA14 +#define PIN_A5995_ENABLE2 (18) //PA05 analogInputToDigitalPin(PIN_A4)) +#define PIN_A5995_MODE1 (8) //PA06 TCC1 WO[0] +#define PIN_A5995_MODE2 (7) //PA21 TCC0 WO[4] //3 +#define PIN_A5995_PHASE1 (6) //PA20 TCC0 WO[6] //2 +#define PIN_A5995_PHASE2 (5) //PA15 TCC0 W0[5] //1 +#define PIN_A5995_VREF1 (4) //PA08 +#define PIN_A5995_VREF2 (9) //PA07 +#define PIN_A5995_SLEEPn (25) //RXLED + + +#ifndef MECHADUINO_HARDWARE +#define PIN_YELLOW_LED (8) +#endif + + + + +#ifdef NEMA_23_10A_HW +#undef PIN_YELLOW_LED +#define PIN_YELLOW_LED (26) //TXLED (PA27) +#endif //NEMA_23_10A_HW + + +#define PIN_RED_LED (13) +#define PIN_A4954_IN3 (5) +#define PIN_A4954_IN4 (6) +#define PIN_A4954_IN2 (7) +#ifdef MECHADUINO_HARDWARE +#define PIN_A4954_IN1 (8) +#else +#define PIN_A4954_IN1 (18) //analogInputToDigitalPin(PIN_A4)) +#endif +#define PIN_A4954_VREF34 (4) +#define PIN_A4954_VREF12 (9) + + + +//Here are some useful macros +#define DIVIDE_WITH_ROUND(x,y) (((x)+(y)/2)/(y)) + + +#define GPIO_LOW(pin) {PORT->Group[g_APinDescription[(pin)].ulPort].OUTCLR.reg = (1ul << g_APinDescription[(pin)].ulPin);} +#define GPIO_HIGH(pin) {PORT->Group[g_APinDescription[(pin)].ulPort].OUTSET.reg = (1ul << g_APinDescription[(pin)].ulPin);} +#define GPIO_OUTPUT(pin) {PORT->Group[g_APinDescription[(pin)].ulPort].PINCFG[g_APinDescription[(pin)].ulPin].reg &=~(uint8_t)(PORT_PINCFG_INEN) ; PORT->Group[g_APinDescription[(pin)].ulPort].DIRSET.reg = (uint32_t)(1<Group[g_APinDescription[(pin)].ulPort].PINCFG[g_APinDescription[(pin)].ulPin].reg &=~(uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PMUXEN) ; PORT->Group[g_APinDescription[(pin)].ulPort].DIRSET.reg = (uint32_t)(1<Group[g_APinDescription[(pin)].ulPort].PINCFG[g_APinDescription[(pin)].ulPin].reg &=~(uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PMUXEN);} +#define GPIO_READ(ulPin) {(PORT->Group[g_APinDescription[ulPin].ulPort].IN.reg & (1ul << g_APinDescription[ulPin].ulPin)) != 0} +#define PIN_PERIPH(pin) {PORT->Group[g_APinDescription[(pin)].ulPort].PINCFG[g_APinDescription[(pin)].ulPin].reg |= PORT_PINCFG_PMUXEN;} +//sets up the pins for the board +static void boardSetupPins(void) +{ + //setup switch pins +#ifdef PIN_SW1 + pinMode(PIN_SW1, INPUT_PULLUP); + pinMode(PIN_SW3, INPUT_PULLUP); + pinMode(PIN_SW4, INPUT_PULLUP); +#endif + + pinMode(PIN_STEP_INPUT, INPUT_PULLUP); + pinMode(PIN_DIR_INPUT, INPUT_PULLUP); + +#ifdef PIN_ENABLE + pinMode(PIN_ENABLE, INPUT_PULLUP); //default error pin as enable pin with pull up +#endif + pinMode(PIN_ERROR, INPUT_PULLUP); //default error pin as enable pin with pull up + + pinMode(PIN_AS5047D_CS,OUTPUT); + digitalWrite(PIN_AS5047D_CS,LOW); //pull CS LOW by default (chip powered off) + + //turn the AS5047D off by default +#ifdef PIN_AS5047D_PWR + pinMode(PIN_AS5047D_PWR,OUTPUT); + digitalWrite(PIN_AS5047D_PWR,HIGH); +#endif + + + + pinMode(PIN_MOSI,OUTPUT); + digitalWrite(PIN_MOSI,LOW); + pinMode(PIN_SCK,OUTPUT); + digitalWrite(PIN_SCK,LOW); + pinMode(PIN_MISO,INPUT); + + //setup the A4954 pins + digitalWrite(PIN_A4954_IN3,LOW); + pinMode(PIN_A4954_IN3,OUTPUT); + digitalWrite(PIN_A4954_IN4,LOW); + pinMode(PIN_A4954_IN4,OUTPUT); + digitalWrite(PIN_A4954_IN2,LOW); + pinMode(PIN_A4954_IN2,OUTPUT); + digitalWrite(PIN_A4954_IN1,LOW); + pinMode(PIN_A4954_IN1,OUTPUT); + + //setup the PWM for current on the A4954, set for low current + digitalWrite(PIN_A4954_VREF12,LOW); + digitalWrite(PIN_A4954_VREF34,LOW); + pinMode(PIN_A4954_VREF34, OUTPUT); + pinMode(PIN_A4954_VREF12, OUTPUT); + + + + pinMode(PIN_RED_LED,OUTPUT); +#ifdef PIN_YELLOW_LED + pinMode(PIN_YELLOW_LED,OUTPUT); + digitalWrite(PIN_YELLOW_LED,HIGH); +#endif +} + +#ifdef NEMA17_SMART_STEPPER_3_21_2017 +static float GetMotorVoltage(void) +{ + uint32_t x; + float f; + //the motor voltage is 1/101 of the adc + x=analogRead(PIN_VMOTOR); //this should be a 10bit value mapped to 3.3V + f=(float)x*3.3/1024.0*101.0; + return f; +} +#endif + +static void inline YELLOW_LED(bool state) +{ +#ifdef PIN_YELLOW_LED + digitalWrite(PIN_YELLOW_LED,!state); +#endif +} + +static void inline RED_LED(bool state) +{ + digitalWrite(PIN_RED_LED,state); +} + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define ABS(a) (((a)>(0))?(a):(-(a))) +#define DIV(x,y) (((y)>(0))?((x)/(y)):(4294967295)) +#define SIGN(x) (((x) > 0) - ((x) < 0)) + +#define NVIC_IS_IRQ_ENABLED(x) (NVIC->ISER[0] & (1 << ((uint32_t)(x) & 0x1F)))!=0 + +static inline uint8_t getPinMux(uint16_t ulPin) +{ + uint8_t temp; + if ((ulPin & 0x01)==0) + { + temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXE( 0xF ) ; + }else + { + temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg)>>4 & 0xF; + } + return temp; +} + + +static inline uint8_t getPinCfg(uint16_t ulPin) +{ + uint8_t temp; + + temp = PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg; + return temp; +} + +static inline void setPinCfg(uint16_t ulPin, uint8_t val) +{ + PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=val; +} + + + +static inline void setPinMux(uint16_t ulPin, uint8_t val) +{ + uint8_t temp; + temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg); + if ((ulPin & 0x01)==0) + { + //if an even pin + temp = (temp & 0xF0) | (val & 0x0F); + }else + { + temp = (temp & 0x0F) | ((val<<4) & 0x0F); + } + PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg=temp; + PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ; // Enable port mux +} + +static inline void SET_PIN_PERHERIAL(uint16_t ulPin,EPioType ulPeripheral) +{ + if ( g_APinDescription[ulPin].ulPin & 1 ) // is pin odd? + { + uint32_t temp ; + + // Get whole current setup for both odd and even pins and remove odd one + temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXE( 0xF ) ; + // Set new muxing + PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXO( ulPeripheral ) ; + // Enable port mux + PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ; + } + else // even pin + { + uint32_t temp ; + + temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXO( 0xF ) ; + PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXE( ulPeripheral ) ; + PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ; // Enable port mux + } +} + + +//the Arduino delay function requires interrupts to work. +// if interrupts are disabled use the delayMicroseconds which is a spin loop +static inline void DelayMs(uint32_t ms) +{ + uint32_t prim; + /* Read PRIMASK register, check interrupt status before you disable them */ + /* Returns 0 if they are enabled, or non-zero if disabled */ + prim = __get_PRIMASK(); + + if (prim==0) + { + delay(ms); + }else + { + while(ms) + { + delayMicroseconds(1000); + ms--; + } + } +} + +#endif//__BOARD_H__ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.cpp new file mode 100644 index 0000000..e9ae16c --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.cpp @@ -0,0 +1,599 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "calibration.h" +#include "Flash.h" +#include "nonvolatile.h" +#include "board.h" //for divide with rounding macro +#include "utils.h" + + +static uint16_t getTableIndex(uint16_t value) +{ + int32_t x; + + x=((int32_t)value*CALIBRATION_TABLE_SIZE)/CALIBRATION_STEPS; //the divide is a floor not a round which is what we want + return (uint16_t)x; + +} +static uint16_t interp(Angle x1, Angle y1, Angle x2, Angle y2, Angle x) +{ + int32_t dx,dy,dx2,y; + dx=x2-x1; + dy=y2-y1; + dx2=x-x1; + y=(int32_t)y1+DIVIDE_WITH_ROUND((dx2*dy),dx); + if (y<0) + { + y=y+CALIBRATION_STEPS; + } + return (uint16_t)y; +} + +static void printData(int32_t *data, int32_t n) +{ + int32_t i; + Serial.print("\n\r"); + for (i=0; iFastCal.angle[x]; + }else + { + return reverseLookup(encoderAngle); + } +#else + return reverseLookup(encoderAngle) +#endif +} + +Angle CalibrationTable::reverseLookup(Angle encoderAngle) +{ + + int32_t i=0; + int32_t a1,a2; + int32_t x; + int16_t y; + int32_t min,max; + min=(uint16_t)table[0].value; + max=min; + + + + for (i=0; imax) + { + max=x; + } + } + + + x=(uint16_t)encoderAngle; + if (xCALIBRATION_STEPS/2) + { + if (a1=a1 && x<=a2) || + (x>=a2 && x<=a1) ) + { + //LOG("%d", i); + // inerpolate results and return + //LOG("%d %d %d",a1,a2,x); + //LOG("%d,%d",(i*CALIBRATION_MAX)/CALIBRATION_TABLE_SIZE,((i+2)*CALIBRATION_MAX)/CALIBRATION_TABLE_SIZE); + + y=interp(a1, DIVIDE_WITH_ROUND((i*CALIBRATION_STEPS),CALIBRATION_TABLE_SIZE), a2, DIVIDE_WITH_ROUND( ((i+1)*CALIBRATION_STEPS),CALIBRATION_TABLE_SIZE), x); + + return y; + } + i++; + } + ERROR("WE did some thing wrong"); + + + + +} + + +void CalibrationTable::smoothTable(void) +{ + uint16_t b[]={1,2,4,5,4,2,1}; + uint16_t sum_b=19; //sum of b filter + + int32_t data[CALIBRATION_TABLE_SIZE]; + int32_t table2[CALIBRATION_TABLE_SIZE]; + + int32_t i; + int32_t offset=0; + int32_t startNum; + + //first lets handle the wrap around in the table + for (i=0; i0 && offset==0) + { + if(((uint16_t)table[i-1].value-(uint16_t)table[i].value) <-32768) + { + offset=-65536; + } + + if (((uint16_t)table[i-1].value-(uint16_t)table[i].value) > 32768) + { + offset=65536; + } + } + table2[i]=(int32_t)((uint16_t)table[i].value)+offset; + } + + //Serial.print("after wrap\n\r"); + //printData(table2,CALIBRATION_TABLE_SIZE); + + //remove the starting offset and compensate table for index + startNum=table2[0]; + for (i=0; i=CALIBRATION_TABLE_SIZE) + { + ix=ix-CALIBRATION_TABLE_SIZE; + } + if (i==0) + { + LOG("index %d",ix); + } + sum=sum+table2[ix]*b[ib]; + ib++; + } + sum=DIVIDE_WITH_ROUND(sum,sum_b); + data[i]=sum; + } + + //Serial.print("after filter\n\r"); + //printData(data,CALIBRATION_TABLE_SIZE); + + //add in offset and the phase compenstation + for (i=0; i=65536) + { + data[i]=data[i]-65536; + } + } + + //Serial.print("after wrap added\n\r"); + //printData(data,CALIBRATION_TABLE_SIZE); + + //save new table + for (i=0; iCalibrationTable,sizeof(data)); + createFastCal(); + + LOG("after writting status is %d",data.status); + loadFromFlash(); + +} + +void CalibrationTable::loadFromFlash(void) +{ + FlashCalData_t data; + int i; + LOG("Reading Calbiration to Flash"); + memcpy(&data, &NVM->CalibrationTable,sizeof(data)); + for (i=0; iCalibrationTable.status); + return NVM->CalibrationTable.status; +} + + +void CalibrationTable::createFastCal(void) +{ +#ifdef NZS_FAST_CAL + int32_t i; + uint16_t cs=0; + uint16_t data[256]; + int32_t j; + j=0; + cs=0; + LOG("setting fast calibration"); + for (i=0; i<16384; i++) + { + + uint16_t x; + x=reverseLookup(i*4); + data[j]=x; + j++; + if (j>=256) + { + flashWrite(&NVM->FastCal.angle[i-255],data,256*sizeof(uint16_t)); + //LOG("Wrote fastcal at index %d-%d", i-255, i); + j=0; + } + cs+=x; + } + //update the checksum + flashWrite(&NVM->FastCal.checkSum,&cs,sizeof(uint16_t)); + fastCalVaild=true; + + //this is a quick test + /* + for (i=0; i<16384; i++) + { + LOG("fast Cal %d,%d,%d",i,NVM->FastCal.angle[i],(uint32_t)reverseLookup(i*4)); + } + */ +#endif +} +void CalibrationTable::updateFastCal(void) +{ +#ifdef NZS_FAST_CAL + int32_t i; + uint16_t cs=0; + uint16_t data[256]; + int32_t j; + bool NonZero=false; + for (i=0; i<16384; i++) + { + cs+=NVM->FastCal.angle[i]; + if (cs != 0) + { + NonZero=true; + } + } + if (cs!=NVM->FastCal.checkSum || NonZero==false) + { + createFastCal(); + } + else + { + LOG("fast cal is valid"); + fastCalVaild=true; + } +#endif +} + +void CalibrationTable::init(void) +{ + int i; + + if (true == flashGood()) + { + loadFromFlash(); + updateFastCal(); + }else + { + for (i=0; iCALIBRATION_STEPS/2) + { + dist=dist-CALIBRATION_STEPS; + } + + //if our distance is larger than size between calibration points in table we will ignore this sample + if (dist>CALIBRATION_STEPS/CALIBRATION_TABLE_SIZE) + { + //spans two or more table calibration points for this implementation we will not use + lastIndex=(int32_t)index; + lastValue=value; + return; + } + + //now lets see if the values are above and below a table calibration point + dist= abs(getTableIndex(lastAngle)-getTableIndex(actualAngle)); + if (dist != 0) //if the two indexs into table are not the same it spans a calibration point in table. + { + //the two span a set calibation table point. + uint16_t newValue; + newValue=interp(lastAngle, lastEncoderValue, actualAngle, encoderValue, getTableIndex(actualAngle)*(CALIBRATION_STEPS/CALIBRATION_TABLE_SIZE)) + //this new value is our best guess as to the correct calibration value. + updateTableValue(getTableIndex(actualAngle),newValue); + } else + { + //we should calibate the table value for the point the closest + } + + + + + + } + lastAngle=(int32_t)actualAngle; + lastEncoderValue=encoderValue; + +} +#endif + +//when we are microstepping and are in between steps the probability the stepper motor did not move +// is high. That is the actualAngle will be correct but the encoderValue will be behind due to not having enough torque to move motor. +// Therefore we only want to update the calibration on whole steps where we have highest probability of things being correct. +void CalibrationTable::updateTable(Angle actualAngle, Angle encoderValue) +{ + int32_t dist, index; + Angle tableAngle; + + index = getTableIndex((uint32_t)actualAngle+CALIBRATION_STEPS/CALIBRATION_TABLE_SIZE/2); //add half of distance to next entry to round to closest table index + + tableAngle=(index*CALIBRATION_STEPS)/CALIBRATION_TABLE_SIZE; //calculate the angle for this index + + dist=tableAngle-actualAngle; //distance to calibration table angle + + //LOG("Dist is %d",dist); + if (abs(dist)=CALIBRATION_TABLE_SIZE) + { + indexHigh -= CALIBRATION_TABLE_SIZE; + } + + //LOG("AngleLow %d, AngleHigh %d",angleLow,angleHigh); + //LOG("TableLow %u, TableHigh %d",(uint16_t)table[indexLow].value,(uint16_t)table[indexHigh].value); + y1=table[indexLow].value; + y2=table[indexHigh].value; + + //handle the wrap condition + if (abs(y2-y1)>CALIBRATION_STEPS/2) + { + if (y2=CALIBRATION_STEPS) + { + value=value-CALIBRATION_STEPS; + } + + err=table[indexLow].error; + if (table[indexHigh].error > err) + { + err=table[indexHigh].error; + } + + if (table[indexLow].error == CALIBRATION_ERROR_NOT_SET || + table[indexHigh].error == CALIBRATION_ERROR_NOT_SET) + { + err=CALIBRATION_ERROR_NOT_SET; + } + ptrData->value=value; + ptrData->error=err; + + return 0; + +} + +Angle CalibrationTable::getCal(Angle actualAngle) +{ + CalData_t data; + getValue(actualAngle, &data); + return data.value; +} + + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.h b/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.h new file mode 100644 index 0000000..eaba5a6 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.h @@ -0,0 +1,104 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __CALIBRAITON_H__ +#define __CALIBRAITON_H__ + +#include +#include "syslog.h" +#include "angle.h" + + +//this file implements a table that is linearly interpolated circular calibration table +// it is assumed the data wraps around, ie you interpolated 65536==0 +//we want this to be "whole" steps, for 1.8 degree motors this should be 200. +// 200 will work for 0.9 degree too, but could be 400. However 400 is not good for 1.8 degree motors +#define CALIBRATION_TABLE_SIZE (200) + +#define CALIBRATION_STEPS ((uint32_t)ANGLE_STEPS) // this is one rotation ie 0-65535 aka 65536 steps is 0-360 degrees + +#define CALIBRATION_ERROR_NOT_SET (-1) //indicated that the calibration value is not set. + +#define CALIBRATION_UPDATE_RATE (32) //number of samples to keep 1 pole running average +#define CALIBRATION_MIN_ERROR (4) //the minimal expected error on our calibration 4 ~=+/0.2 degrees + + +typedef struct { + uint16_t table[CALIBRATION_TABLE_SIZE]; + bool status; +} FlashCalData_t; + + + + + +typedef struct { + Angle value; //cal value + int16_t error; //error assuming it is constantly updated +} CalData_t; + +class CalibrationTable +{ + private: + CalData_t table[CALIBRATION_TABLE_SIZE]; + + bool fastCalVaild=false; + void loadFromFlash(void); + bool flashGood(void); //returns true if the flash copy of calibration is valid + + void updateFastCal(void); + void createFastCal(void); + + public: + void init(void); + void saveToFlash(void); //saves the calibration to flash + bool updateTableValue(int32_t index, int32_t value); + void updateTable(Angle actualAngle, Angle encoderValue); + int getValue(Angle actualAngle, CalData_t *ptrData); + Angle getCal(Angle actualAngle); + bool calValid(void); + Angle reverseLookup(Angle encoderAngle); //this turns encoder angle into real angle + void printCalTable(void); + void smoothTable(void); + + Angle fastReverseLookup(Angle encoderAngle); +}; + + + + +#endif //__CALIBRAITON_H__ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/command.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/command.cpp new file mode 100644 index 0000000..bc6412a --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/command.cpp @@ -0,0 +1,381 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#include "command.h" +#include + + +#define ASCII_BACKSPACE 0x08 +#define ASCII_ESC 0x1B +#define ASCII_UP_ARROW 0x9b +//const char CMD_ANSI_UP[]= {ASCII_ESC,'[','A',0}; + +int strcicmp(char const *a, char const *b) +{ + for (;; a++, b++) { + int d = tolower(*a) - tolower(*b); + if (d != 0 || !*a) + return d; + } +} + +int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size) ) +{ + ptrUart->kbhit=kbhit; + ptrUart->getch=getch; + ptrUart->putch=putch; + ptrUart->puts=puts; + ptrUart->histIndex=0; + ptrUart->buffIndex=0; + return 0; +} + +#ifdef PGM_P //check and see if the PGM_P is defined for the AVR + +int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...) +{ + int ret=0; + char vastr[MAX_STRING]={0}; + //char str[MAX_STRING]={0}; + char *ptr; + va_list ap; + + //LOG("Command printf"); + memset(vastr,0,MAX_STRING); + va_start(ap,fmt); + ret=vsprintf(vastr,(const char *)fmt,ap); + //ret=sprintf(vastr,"%s\r\n",str); + //LOG("%s",vastr); + if (ptrUart->puts!=NULL) + { + return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret); + } + + if (ptrUart->putch!=NULL) + { + ptr=vastr; + while(*ptr) + { + ptrUart->putch(*ptr++); + } + + return ret; + } + return 0; +} + + +#else +int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...) +{ + int ret=0; + char vastr[MAX_STRING]={0}; + char *ptr; + va_list ap; + + + memset(vastr,0,MAX_STRING); + va_start(ap,fmt); + ret=vsprintf(vastr,(char *)fmt,ap); + if (ptrUart->puts!=NULL) + { + return ptrUart->puts((uint8_t *)vastr, (uint8_t)ret); + } + + if (ptrUart->putch!=NULL) + { + ptr=vastr; + while(*ptr) + { + ptrUart->putch(*ptr++); + } + + return ret; + } + return 0; +} +#endif + + +// the delimiter is command/parameter delimiter +// by default a ' '0x20 is used but for the TDR with GUI a ':' was preferred, not sure why +// set to ' '/0x20 if you want normal command parsing, like DOS +unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor ) +{ + char *ptr; + char *ptr2; + unsigned int i; + //char cmd[MAX_STRING]; + char buff[MAX_CMD_LENGTH]; + char argv[MAX_ARGS][MAX_ARG_LENGTH]; + char *ptrArgv[MAX_ARGS]; + unsigned int numArgs; + int emptyArg=0; + + sCommand cmd_list; + + + while (*str==0x20 || *str=='\n' || *str=='\r' || *str=='\t') str++; + //first we need find command and arguments + ptr=strchr(str,delimitor); //find first char + + //LOG("2parsing %s",str); + + + if (ptr==0) + { + //we have two options, frist whole thing is command + //second bad command + if(strlen(str)>0) + ptr=str+strlen(str); + else + return 0; //bad command + } + + //copy string to command buffer. + i=0; + ptr2=str; + while(ptr!=0 && ptr!=ptr2 && i<(MAX_CMD_LENGTH-1)) + { + //if (*ptr2!='\n' && *ptr2!='\r') //do not include newlines + { + buff[i++]=*ptr2; + } + ptr2++; + } + buff[i]=0; + + //now buff contains the command let's get the args + numArgs=0; + while(*ptr!=0 && (*ptr==' ' || *ptr==delimitor)) + ptr++; //increment pointer past ' ' + if (*ptr!=0) + { + if (*ptr==34) // " char + { + ptr++; + ptr2=strchr(ptr,34); //find match + } else if (*ptr==39) // 'char + { + ptr++; + ptr2=strchr(ptr,39); //find match + } else + { + ptr2=strchr(ptr,delimitor); + } + if (ptr2==0) + { + //we have two options, frist whole thing is command + //second bad command + //LOG("strlen ptr is %d",strlen(ptr)); + if(strlen(ptr)>0) + ptr2=ptr+strlen(ptr); + } + emptyArg=0; + while((ptr2!=0 && numArgs0) + ptr2=ptr+strlen(ptr); + } + } + } + } + + for(i=0; ikbhit()) + { + ptrUart->data=ptrUart->getch(); + + //echo the data + ptrUart->putch(ptrUart->data); + + //if the data is the CR we need to process buffer + if (ptrUart->data==0x0D) + { + ptrUart->putch(0x0A); + if (strlen(ptrUart->buffer)>0) + { + if (ptrUart->lastChar!=ASCII_UP_ARROW) + { + strcpy(ptrUart->bufferHist[ptrUart->histIndex],ptrUart->buffer); + ptrUart->histIndex=(ptrUart->histIndex+1) % CMD_HISTORY; + } + CommandParse(ptrUart,ptrCmds,ptrUart->buffer,delimitor); + } + + CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt); + ptrUart->buffIndex=0; + ptrUart->buffer[ptrUart->buffIndex]=0; + } + + if (ptrUart->data==ASCII_BACKSPACE) //backspace + { + if (ptrUart->buffIndex>0) + { + ptrUart->buffIndex--; + ptrUart->buffer[ptrUart->buffIndex]='\0'; + //Echo the backspace + ptrUart->putch(' '); + ptrUart->putch(ASCII_BACKSPACE); + } + }else if (ptrUart->data != 0x0A && ptrUart->data !=0x0D && ptrUart->data<127) + { + ptrUart->buffer[ptrUart->buffIndex++]=ptrUart->data; + ptrUart->buffer[ptrUart->buffIndex]=0; + } + if (ptrUart->buffIndex>=(MAX_CMD_LENGTH-1)) + { + CommandPrintf(ptrUart,PSTR("\n\rERROR: Command buffer overflow\n\r"));\ + ERROR("Command buffer overflow"); + ptrUart->buffIndex=0; + ptrUart->buffer[0]=0; + CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt); + } + } + + + if (strstr(ptrUart->buffer,ANSI_UP)) //up arrow + { + uint8_t i; + + CommandPrintf(ptrUart,PSTR("\n\r%s"),cmdPrompt); + i=CMD_HISTORY-1; + if (ptrUart->histIndex>0) + { + i=ptrUart->histIndex-1; + } + if (strlen(ptrUart->bufferHist[i])>0) + { + strcpy(ptrUart->buffer,ptrUart->bufferHist[i]); + ptrUart->buffIndex=strlen(ptrUart->buffer); + CommandPrintf(ptrUart,PSTR("%s"),ptrUart->buffer); + }else + { + ptrUart->buffIndex=0; + ptrUart->buffer[0]=0; + } + ptrUart->data=ASCII_UP_ARROW; + } + + + ptrUart->lastChar=ptrUart->data; + return 0; +} + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/command.h b/firmware_smartstepper_trikarus/stepper_nano_zero/command.h new file mode 100644 index 0000000..3af3df2 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/command.h @@ -0,0 +1,179 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __COMMAND_H +#define __COMMAND_H + +#include +#include +#include "syslog.h" +/* + * Usage: + * + #include + #include "uart_e0.h" + + sCmdUart KeyfobCmdUart; // UART used for the keyfob command line interface + + CMD_STR(help,"Displays this message"); + + //List of supported commands + sCommand KeyfobCmds[] = + { + COMMAND(help), + {"",0,""}, //End of list signal + }; + + // print out the help strings for the commands + static int help_cmd(sCmdUart *ptrUart,int argc, char * argv[]) + { + sCommand cmd_list; + int i; + + //now let's parse the command + i=0; + memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand)); + while(cmd_list.function!=0) + { + + CommandPrintf(ptrUart,(cmd_list.name)); + CommandPrintf(ptrUart,PSTR(" - ")); + CommandPrintf(ptrUart,(cmd_list.help)); + CommandPrintf(ptrUart,PSTR("\n\r")); + i=i+1; + memcpy(&cmd_list, &KeyfobCmds[i], sizeof(sCommand)); + } + return 0; + } + + uint8_t KeyfobCmdGetChar(void) + { + uint8_t c; + if (UARTE0_getc(&c)!=0) + { + ERROR("Uart getchar failed"); + return 0; + } + return c; + } + int KeyfobCmdInit(PIN tx_pin, PIN rx_pin, uint32_t baud) + { + LOG("UARTE0 init"); + UARTE0_Init(tx_pin, rx_pin, baud); + CommandInit(&KeyfobCmdUart, UARTE0_kbhit, KeyfobCmdGetChar, UARTE0_putc,NULL); //set up the UART structure + return 0; + } + + int KeyfobCmdProcess(void) + { + return CommandProcess(&KeyfobCmdUart,KeyfobCmds,' ',KEYFOB_CMD_PROMPT); + } + + Advantages: + 1. You can actually have more than one UART/device connected to same command line interface. + 2. works with harvard machines to save SRAM space using the PSTR functionality + 3. You can swap out commands "on the fly" + + + */ +#define MAX_CMD_LENGTH 60 +#define MAX_ARGS 10 +#define MAX_ARG_LENGTH 40 +#define CMD_HISTORY 3 //number of commands in history buffer +#define ASCII_BACKSPACE 0x08 +#define ASCII_ESC 0x1B +#define ASCII_UP_ARROW 0x9b +#define ANSI_UP "\x1B[A\0" + +#define MAX_STRING 255 +//const char ANSI_UP[]= {ASCII_ESC,'[','A',0}; + +typedef struct { + uint8_t (*kbhit)(void); + uint8_t (*getch)(void); + uint8_t (*putch)(char data); + uint8_t (*puts)(uint8_t *buffer, uint8_t size); + uint8_t data; + char buffer[MAX_CMD_LENGTH]; + + char bufferHist[CMD_HISTORY][MAX_CMD_LENGTH]; + uint8_t histIndex; + uint8_t buffIndex; + uint8_t lastChar; +}sCmdUart; + + +#define COMMAND(NAME) { NAME ## _str, NAME ## _cmd, NAME ## _help} + + +#ifdef PGM_P //check and see if the PGM_P is defined for the AVR + +//If so then we use the strings in flash not SRAM +#define CMD_STR(NAME,STR) static const char NAME ## _help[] PROGMEM = STR; static const char NAME ## _str[] PROGMEM = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **); +//Command structure +typedef struct +{ + PGM_P name; + int (*function) (sCmdUart *ptrUart,int, char **); + PGM_P help; +} sCommand; +int CommandPrintf(sCmdUart *ptrUart, const char *fmt, ...); + +#else + +#define CMD_STR(NAME,STR) static char NAME ## _help[] = STR; static char NAME ## _str[] = #NAME; static int NAME ##_cmd(sCmdUart *ptrUart,int, char **); + +//Command structure +typedef struct +{ + char *name; + int (*function) (sCmdUart *ptrUart,int, char **); + char *help; +} sCommand; + +int CommandPrintf(sCmdUart *ptrUart, char *fmt, ...); +#endif + + +int CommandInit(sCmdUart *ptrUart, uint8_t (*kbhit)(void), uint8_t (*getch)(void),uint8_t (*putch)(char data),uint8_t (*puts)(uint8_t *buffer, uint8_t size)); +unsigned int CommandParse(sCmdUart *ptrUart,sCommand *ptrCmds, char *str, char delimitor); +int CommandProcess(sCmdUart *ptrUart,sCommand *ptrCmds, char delimitor, char *cmdPrompt); + + + +#endif + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/commands.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/commands.cpp new file mode 100644 index 0000000..a6c1c56 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/commands.cpp @@ -0,0 +1,1658 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "commands.h" +#include "command.h" +#include "calibration.h" +#include "stepper_controller.h" +#include +#include "nonvolatile.h" +#include "Reset.h" +#include "nzs.h" +#include "ftoa.h" +#include "board.h" +#include "eeprom.h" +#include "steppin.h" + +extern int32_t dataEnabled; + +#define COMMANDS_PROMPT (":>") +sCmdUart UsbUart; +sCmdUart SerialUart; +sCmdUart HostUart; //uart on the step/dir pins + +static int isPowerOfTwo (unsigned int x) +{ + while (((x % 2) == 0) && x > 1) /* While x is even and > 1 */ + x /= 2; + return (x == 1); +} + + +CMD_STR(help,"Displays this message"); +CMD_STR(getcal,"Prints the calibration table"); +CMD_STR(calibrate,"Calbirates the encoder, should be done with motor disconnected from machine"); +CMD_STR(testcal,"tests the calibaration of the encoder"); +CMD_STR(microsteps,"gets/sets the microstep size, example 'microsteps 16'"); +CMD_STR(step, "Steps motor one step, optionally direction can be set is 'step 1' for reverse"); +CMD_STR(feedback, "enable or disable feedback controller, 'feedback 0' - disables, 'feedback 1' - enables"); +CMD_STR(readpos, "reads the current angle, applies calibration if valid"); +CMD_STR(encoderdiag, "Prints encoder diagnostic") +CMD_STR(spid, "with no arguments prints SIMPLE PID parameters, with arguments sets PID 'sPID Kp Ki Kd' " + "Where Kp,Ki,Kd are floating point numbers"); +CMD_STR(vpid, "with no arguments prints VELOCITY PID parameters, with arguments sets PID 'sPID Kp Ki Kd' " + "Where Kp,Ki,Kd are floating point numbers"); +CMD_STR(ppid, "with no arguments prints POSITIONAL PID parameters, with arguments sets PID 'sPID Kp Ki Kd' " + "Where Kp,Ki,Kd are floating point numbers"); +//CMD_STR(testringing ,"Steps motor at various currents and measures encoder"); +//CMD_STR(microsteperror ,"test error on microstepping") +CMD_STR(dirpin, "with no arguments read dirpin setting, with argument sets direction pin rotation. " + "Changing this also inverts torque mode direction."); +#ifndef PIN_ENABLE +CMD_STR(errorpinmode,"gets/sets the functionality of the error/enable pin"); +#else +CMD_STR(enablepinmode,"gets/sets the functionality of the enable pin"); +#endif + +CMD_STR(errorlimit, "gets/set the error limit which will assert error pin (when error pin is set for error output)"); +CMD_STR(ctrlmode, "gets/set the feedback controller mode of operation"); +CMD_STR(maxcurrent, "gets/set the maximum motor current allowed in milliAmps"); +CMD_STR(holdcurrent, "gets/set the motor holding current in milliAmps, only used in the simple positional PID mode"); +CMD_STR(homecurrent, "gets/set the motor moving and holding currents that will be used when pin A3 is low"); +CMD_STR(motorwiring, "gets/set the motor wiring direction, should only be used by experts"); +CMD_STR(stepsperrotation, "gets/set the motor steps per rotation, should only be used by experts"); + +//CMD_STR(sysparams, "with no arguments read parameters, will set with arguments"); +//CMD_STR(motorparams, "with no arguments read parameters, will set with arguments"); +CMD_STR(boot, "Enters the bootloader"); +CMD_STR(move, "moves encoder to absolute angle in degrees 'move 400.1'"); +//CMD_STR(printdata, "prints last n error terms"); +CMD_STR(velocity, "gets/set velocity in RPMs"); +CMD_STR(torque, "prints torque parameter, with argument sets 'torque t' " + "Where torque is an integer between -128 and 127. The special value 0 disables torque mode and enables position mode."); +CMD_STR(factoryreset, "resets board to factory defaults"); +CMD_STR(stop, "stops the motion planner"); +CMD_STR(setzero, "set the reference angle to zero"); +CMD_STR(data, "enables/disables binary data output"); +CMD_STR(looptime, "returns the control loop processing time"); +CMD_STR(eepromerror, "returns error in degreees from eeprom at power up realtive to current encoder"); +CMD_STR(eepromloc, "returns location in degreees eeprom on power up"); +CMD_STR(eepromwrite, "forces write of location to eeprom"); +CMD_STR(eepromsetloc, "sets the device angle based on EEPROM last reading, compenstates for error") +CMD_STR(setpos, "sets the current angle in degrees"); +CMD_STR(reboot, "reboots the unit"); +CMD_STR(homepin, "sets the pin used to drop to homing current"); +CMD_STR(homeangledelay, "sets the angle delay in dropping to homing current"); +#ifdef PIN_ENABLE +CMD_STR(home, "moves the motor until home switch (enable pin) is pulled low. example 'home 360 0.5' move up to 360 degrees at 0.5 RPM ") +#endif +CMD_STR(pinread, "reads pins as binary (bit 0-step, bit 1 - Dir, bit 2 - Enable, bit 3 - Error, bit 4 - A3, bit 5- TX, bit 6 - RX") +CMD_STR(errorpin, "Sets the logic level of error pin") +CMD_STR(geterror, "gets current error") +CMD_STR(getsteps, "returns number of steps seen") +CMD_STR(debug, "enables debug commands out USB") +//List of supported commands +sCommand Cmds[] = +{ + COMMAND(help), + COMMAND(calibrate), + COMMAND(getcal), + COMMAND(testcal), + COMMAND(microsteps), + COMMAND(step), + COMMAND(feedback), + COMMAND(readpos), + COMMAND(encoderdiag), + COMMAND(spid), + COMMAND(vpid), + COMMAND(ppid), + //COMMAND(testringing), + //COMMAND(microsteperror), + COMMAND(dirpin), +#ifndef PIN_ENABLE + COMMAND(errorpinmode), +#else + COMMAND(enablepinmode), +#endif + COMMAND(errorlimit), + COMMAND(ctrlmode), + COMMAND(maxcurrent), + COMMAND(holdcurrent), + COMMAND(homecurrent), + COMMAND(motorwiring), + COMMAND(stepsperrotation), + + //COMMAND(sysparams), + //COMMAND(motorparams), + COMMAND(boot), + COMMAND(move), + //COMMAND(printdata), + COMMAND(velocity), + COMMAND(torque), + COMMAND(factoryreset), + COMMAND(stop), + COMMAND(setzero), + COMMAND(data), + COMMAND(looptime), + COMMAND(eepromerror), + COMMAND(eepromloc), + COMMAND(eepromwrite), + COMMAND(setpos), + COMMAND(reboot), + COMMAND(eepromsetloc), + COMMAND(homepin), + COMMAND(homeangledelay), +#ifdef PIN_ENABLE + COMMAND(home), +#endif + COMMAND(pinread), + COMMAND(errorpin), + COMMAND(geterror), + COMMAND(getsteps), + COMMAND(debug), + {"",0,""}, //End of list signal +}; + +static int debug_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + uint32_t i; + if (argc>=1) + { + i=atol(argv[0]); + SysLogDebug(i); + } +} + +static int getsteps_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + int32_t s; + s=(int32_t)getSteps(); +// s=(int32_t)stepperCtrl.getSteps(); + CommandPrintf(ptrUart,"steps %" PRIi32 "\n\r",s); + return 0; +} +static int geterror_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + float f; + char str[30]; + f=ANGLE_T0_DEGREES(stepperCtrl.getLoopError()); + ftoa(f,str,2,'f'); + CommandPrintf(ptrUart,"error %s deg",str); + return 0; +} + + +static int errorpin_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (argc==1) + { + + SystemParams_t params; + + memcpy(¶ms,&NVM->SystemParams, sizeof(SystemParams_t) ); + params.errorLogic=atol(argv[0]); + + nvmWriteSystemParms(params); + stepperCtrl.updateParamsFromNVM(); + + } + CommandPrintf(ptrUart,"error pin assert level is %d\n\r",NVM->SystemParams.errorLogic); + return 0; + +} + +static int pinread_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + uint8_t ret=0; + + if (digitalRead(PIN_STEP_INPUT)) + { + ret |= 0x01; + } + if (digitalRead(PIN_DIR_INPUT)) + { + ret |= 0x02; + } +#ifdef PIN_ENABLE + if (digitalRead(PIN_ENABLE)) + { + ret |= 0x04; + } +#endif + if (digitalRead(PIN_ERROR)) + { + ret |= 0x08; + } + if (digitalRead(PIN_A3)) + { + ret |= 0x10; + } + if (digitalRead(30)) + { + ret |= 0x20; + } + if (digitalRead(31)) + { + ret |= 0x40; + } + CommandPrintf(ptrUart,"0x%02X\n\r",ret); + return 0; +} + +#ifdef PIN_ENABLE +static void errorPinISR(void) +{ + SmartPlanner.stop(); //stop the planner +} + + + + +static int home_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + float rpm=1; + float startDegrees=ANGLE_T0_DEGREES(stepperCtrl.getCurrentAngle()); + float finalDegrees=startDegrees+360.0; + char str[20]; + float deg; + + if (argc>=1) + { + finalDegrees=startDegrees+atof(argv[0]); + } + + if (argc>=2) + { + rpm=atof(argv[1]); + } + + //setup a interrupt for the enable pin + attachInterrupt(digitalPinToInterrupt(PIN_ENABLE), errorPinISR, FALLING); + + SmartPlanner.moveConstantVelocity(finalDegrees,rpm); + + while(!SmartPlanner.done()) + { + //do nothing + } + detachInterrupt(digitalPinToInterrupt(PIN_ENABLE)); + deg=ANGLE_T0_DEGREES(stepperCtrl.getCurrentAngle()); + ftoa(deg,str,2,'f'); + CommandPrintf(ptrUart,"home is %s deg\n\r",str); + stepperCtrl.setZero(); + + return 0; +} +#endif + +static int reboot_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + NVIC_SystemReset(); + return 0; +} + +static int setpos_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (argc>=1) + { + int64_t a; + float x; + x=fabs(atof(argv[0])); + a=ANGLE_FROM_DEGREES(x); + stepperCtrl.setAngle(a); + return 0; + } + return 1; +} + +static int eepromwrite_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + eepromFlush(); + return 0; +} +static int eepromerror_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + Angle a; + uint16_t error; + float deg; + char str[20]; + a=(Angle)PowerupEEPROM.encoderAngle; + + LOG("EEPROM encoder %d",(uint16_t)a); + LOG("start encoder %d",(uint16_t)stepperCtrl.getStartupEncoder()); + LOG("current encoder %d",(uint16_t)stepperCtrl.getEncoderAngle()); + a=(a-(Angle)stepperCtrl.getStartupEncoder()); + + + deg=ANGLE_T0_DEGREES((uint16_t)a) ; + if (deg>360.0) + { + deg=deg-360.0; + } + + ftoa(deg,str,2,'f'); + CommandPrintf(ptrUart,"startup error(+/-) %s deg\n\r",str); + + a=(Angle)PowerupEEPROM.encoderAngle; + a=(a-(Angle)stepperCtrl.getEncoderAngle()); + deg=ANGLE_T0_DEGREES((uint16_t)a); + if (deg>360.0) + { + deg=deg-360.0; + } + ftoa(deg,str,2,'f'); + CommandPrintf(ptrUart,"current error(+/-) %s deg\n\r",str); + + return 0; +} + +static int eepromsetloc_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + Angle a; + int64_t deg; + int32_t x; + + x=(uint32_t)PowerupEEPROM.encoderAngle-(uint32_t)stepperCtrl.getEncoderAngle(); + + deg=PowerupEEPROM.angle-x; + + stepperCtrl.setAngle(deg); + return 0; +} + +static int eepromloc_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + Angle a; + int64_t deg; + int32_t x,y; + + deg=PowerupEEPROM.angle; + + deg=(deg*360*100)/(int32_t)ANGLE_STEPS; + x=(deg)/100; + y=abs(deg-(x*100)); + CommandPrintf(ptrUart,"%d.%0.2d deg\n\r",x,y); + return 0; +} +static int looptime_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + + CommandPrintf(ptrUart,"%dus",stepperCtrl.getLoopTime()); + return 0; +} + +static int setzero_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + stepperCtrl.setZero(); + return 0; +} + + +static int stop_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + SmartPlanner.stop(); + return 0; +} + +static int data_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (argc == 1) + { + uint32_t x; + + x=atol(argv[0]); + dataEnabled=x; + return 0; + } + return 1; +} + + + +static int stepsperrotation_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + + if (argc == 0) + { + uint32_t x; + x=NVM->motorParams.fullStepsPerRotation; + CommandPrintf(ptrUart,"full steps per rotation %u\n\r",x); + return 0; + } + + if (argc == 1) + { + uint32_t x; + + x=atol(argv[0]); + + if (x==200 || x==400) + { + MotorParams_t motorParams; + + memcpy(&motorParams,&NVM->motorParams, sizeof(motorParams) ); + motorParams.fullStepsPerRotation=x; + + nvmWriteMotorParms(motorParams); + stepperCtrl.updateParamsFromNVM(); + + + x=NVM->motorParams.fullStepsPerRotation; + CommandPrintf(ptrUart,"full steps per rotation %u\n\r",x); + CommandPrintf(ptrUart,"please power cycle board\n\r"); + return 0; + } + + } + CommandPrintf(ptrUart,"usage 'stepsperrotation 200' or 'stepsperrotation 400'\n\r"); + + return 1; +} + +static int motorwiring_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + + if (argc == 0) + { + uint32_t x; + x=NVM->motorParams.motorWiring; + CommandPrintf(ptrUart,"motor wiring %u\n\r",x); + return 0; + } + + if (argc == 1) + { + uint32_t x; + + x=atol(argv[0]); + + if (x<=1) + { + MotorParams_t motorParams; + + memcpy(&motorParams,&NVM->motorParams, sizeof(motorParams) ); + motorParams.motorWiring=x; + + nvmWriteMotorParms(motorParams); + stepperCtrl.updateParamsFromNVM(); + + + x=NVM->motorParams.motorWiring; + CommandPrintf(ptrUart,"motor wiring %u\n\r",x); + CommandPrintf(ptrUart,"please power cycle board\n\r"); + return 0; + } + + } + CommandPrintf(ptrUart,"usage 'motorwiring 0' or 'motorwiring 1'\n\r"); + + return 1; +} + + +static int homeangledelay_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + float f; + char str[30]; + + if (argc == 1) + { + f=atof(argv[0]); + + SystemParams_t params; + + memcpy(¶ms,&NVM->SystemParams, sizeof(SystemParams_t) ); + params.homeAngleDelay=ANGLE_FROM_DEGREES(f); + + nvmWriteSystemParms(params); + stepperCtrl.updateParamsFromNVM(); + + } + + f=ANGLE_T0_DEGREES(NVM->SystemParams.homeAngleDelay); + ftoa(f,str,2,'f'); + CommandPrintf(ptrUart,"home angle delay %s\n\r",str); + return 0; +} + +static int homepin_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + int32_t x; + if (argc == 0) + { + x=NVM->SystemParams.homePin; + CommandPrintf(ptrUart,"home pin %d\n\r",x); + return 0; + } + + if (argc == 1) + { + x=atol(argv[0]); + + SystemParams_t params; + + memcpy(¶ms,&NVM->SystemParams, sizeof(SystemParams_t) ); + params.homePin=x; + + nvmWriteSystemParms(params); + stepperCtrl.updateParamsFromNVM(); + + + x=NVM->SystemParams.homePin; + CommandPrintf(ptrUart,"home pin %d\n\r",x); + return 0; + + } + + CommandPrintf(ptrUart, "use 'sethomepin 17' to set maximum home pin to A3"); + + return 1; +} + + +static int homecurrent_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + uint32_t x,y; + if (argc == 0) + { + x=NVM->motorParams.homeMa; + y=NVM->motorParams.homeHoldMa; + CommandPrintf(ptrUart,"current %umA, %umA\n\r",x,y); + return 0; + } + + if (argc == 1) + { + x=atol(argv[0]); + + MotorParams_t motorParams; + + memcpy(&motorParams,&NVM->motorParams, sizeof(motorParams) ); + motorParams.homeMa=x; + + nvmWriteMotorParms(motorParams); + stepperCtrl.updateParamsFromNVM(); + + + x=NVM->motorParams.homeMa; + y=NVM->motorParams.homeHoldMa; + CommandPrintf(ptrUart,"current %umA, %umA\n\r",x,y); + return 0; + + } + if (argc == 2) + { + x=atol(argv[0]); + y=atol(argv[1]); + + MotorParams_t motorParams; + + memcpy(&motorParams,&NVM->motorParams, sizeof(motorParams) ); + motorParams.homeMa=x; + motorParams.homeHoldMa=y; + + nvmWriteMotorParms(motorParams); + stepperCtrl.updateParamsFromNVM(); + + + x=NVM->motorParams.homeMa; + y=NVM->motorParams.homeHoldMa; + CommandPrintf(ptrUart,"current %umA, %umA\n\r",x,y); + return 0; + + } + CommandPrintf(ptrUart, "use 'homecurrent 1000 500' to set maximum home current to 1.0A and hold to 500ma"); + + return 1; +} + +static int holdcurrent_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + + if (argc == 0) + { + uint32_t x; + x=NVM->motorParams.currentHoldMa; + CommandPrintf(ptrUart,"hold current %u mA\n\r",x); + return 0; + } + + if (argc == 1) + { + uint32_t x; + + x=atol(argv[0]); + + MotorParams_t motorParams; + + memcpy(&motorParams,&NVM->motorParams, sizeof(motorParams) ); + motorParams.currentHoldMa=x; + + nvmWriteMotorParms(motorParams); + stepperCtrl.updateParamsFromNVM(); + + + x=NVM->motorParams.currentHoldMa; + CommandPrintf(ptrUart,"hold current %u mA\n\r",x); + return 0; + + + } + CommandPrintf(ptrUart, "use 'holdcurrent 1000' to set maximum current to 1.0A"); + + return 1; +} + + +static int maxcurrent_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + + if (argc == 0) + { + uint32_t x; + x=NVM->motorParams.currentMa; + CommandPrintf(ptrUart,"max current %u mA\n\r",x); + return 0; + } + + if (argc == 1) + { + uint32_t x; + + x=atol(argv[0]); + + MotorParams_t motorParams; + + memcpy(&motorParams,&NVM->motorParams, sizeof(motorParams) ); + + motorParams.currentMa=x; + nvmWriteMotorParms(motorParams); + stepperCtrl.updateParamsFromNVM(); + + + x=NVM->motorParams.currentMa; + CommandPrintf(ptrUart,"max current %u mA\n\r",x); + return 0; + + + } + CommandPrintf(ptrUart, "use 'maxcurrent 2000' to set maximum current to 2.0A"); + + return 1; +} + + + +static int ctrlmode_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + bool ret; + if (argc == 0) + { + switch(NVM->SystemParams.controllerMode) + { + case CTRL_OFF: + CommandPrintf(ptrUart,"controller Off(0)"); + return 0; + case CTRL_OPEN: + CommandPrintf(ptrUart,"controller Open-loop(1)"); + return 0; + case CTRL_SIMPLE: + CommandPrintf(ptrUart,"controller Simple-Position-PID(2)"); + return 0; + case CTRL_POS_PID: + CommandPrintf(ptrUart,"controller Current-Position-PID(3)"); + return 0; + case CTRL_POS_VELOCITY_PID: + CommandPrintf(ptrUart,"controller Velocity-PID(4)"); + return 0; + case CTRL_TORQUE: + CommandPrintf(ptrUart,"controller Torque(5)"); + return 0; + } + return 1; + } + + if (argc == 1) + { + uint32_t x; + + x=atol(argv[0]); + + if (x<=5) + { + SystemParams_t systemParams; + + memcpy(&systemParams,&NVM->SystemParams, sizeof(systemParams) ); + + systemParams.controllerMode=(feedbackCtrl_t)(x); + + nvmWriteSystemParms(systemParams); + stepperCtrl.updateParamsFromNVM(); + + switch(NVM->SystemParams.controllerMode) + { + case CTRL_OFF: + CommandPrintf(ptrUart,"controller Off(0)"); + return 0; + case CTRL_OPEN: + CommandPrintf(ptrUart,"controller Open-loop(1)"); + return 0; + case CTRL_SIMPLE: + CommandPrintf(ptrUart,"controller Simple-Position-PID(2)"); + return 0; + case CTRL_POS_PID: + CommandPrintf(ptrUart,"controller Current-Position-PID(3)"); + return 0; + case CTRL_POS_VELOCITY_PID: + CommandPrintf(ptrUart,"controller Velocity-PID(4)"); + return 0; + case CTRL_TORQUE: + CommandPrintf(ptrUart,"controller Torque(5)"); + return 0; + + } + return 1; + } + + } + CommandPrintf(ptrUart, "use 'ctrlmode [0 .. 5]' to set control mode"); + + return 1; +} +static int errorlimit_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + bool ret; + char str[20]; + if (argc == 0) + { + float x; + x=ANGLE_T0_DEGREES(NVM->SystemParams.errorLimit); + ftoa(x,str,2,'f'); + CommandPrintf(ptrUart,"errorLimit %s deg\n\r",str); + return 0; + } + + if (argc == 1) + { + float x; + + x=fabs(atof(argv[0])); + + SystemParams_t systemParams; + + memcpy(&systemParams,&NVM->SystemParams, sizeof(systemParams) ); + + systemParams.errorLimit=ANGLE_FROM_DEGREES(x); + + nvmWriteSystemParms(systemParams); + stepperCtrl.updateParamsFromNVM(); + + x=ANGLE_T0_DEGREES(NVM->SystemParams.errorLimit); + ftoa(x,str,2,'f'); + CommandPrintf(ptrUart,"errorLimit %s deg\n\r",str); + return 0; + + + } + CommandPrintf(ptrUart, "use 'errorlimit 1.8' to set error limit to 1.8 degrees"); + + return 1; +} + +/* Stop shaft rotation and return to default mode, + * which is one of CTRL_POS_PID or CTRL_SIMPLE, + * this should be read from nonvolative memory */ +void torqueSetToZeroSpecialBehaviour(void) +{ + if(stepperCtrl.getControlMode() == CTRL_TORQUE) // Don't do anything unless we're exiting torque mode + { + stepperCtrl.acceptPositionAndStealthSwitchMode(NVM->SystemParams.controllerMode); + } +} + + +static int dirpin_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + bool ret; + + if (argc == 0) + { + if (CW_ROTATION == NVM->SystemParams.dirPinRotation) + { + CommandPrintf(ptrUart,"dirpin CW(%d)\n\r",(uint32_t)NVM->SystemParams.dirPinRotation); + }else + { + CommandPrintf(ptrUart,"dirpin CCW(%d)\n\r",(uint32_t)NVM->SystemParams.dirPinRotation); + } + return 0; + } + + if (argc == 1) + { + uint32_t x; + + x=abs(atol(argv[0])); + if (x<=1) + { + + SystemParams_t systemParams; + + memcpy(&systemParams,&NVM->SystemParams, sizeof(systemParams) ); + + systemParams.dirPinRotation=(RotationDir_t)x; + + nvmWriteSystemParms(systemParams); + stepperCtrl.updateParamsFromNVM(); + + if (CW_ROTATION == NVM->SystemParams.dirPinRotation) + { + CommandPrintf(ptrUart,"dirpin CW(%d)\n\r",(uint32_t)NVM->SystemParams.dirPinRotation); + }else + { + CommandPrintf(ptrUart,"dirpin CCW(%d)\n\r",(uint32_t)NVM->SystemParams.dirPinRotation); + } + return 0; + + } + } + CommandPrintf(ptrUart, "used 'dirpin 0' for CW rotation and 'dirpin 1' for CCW"); + + + return 1; +} + +#ifndef PIN_ENABLE +static int errorpinmode_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + bool ret; + + if (argc == 0) + { + if (ERROR_PIN_MODE_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Enable Active High(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + }else if (ERROR_PIN_MODE_ACTIVE_LOW_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Enable active low(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + }else if (ERROR_PIN_MODE_ERROR == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Error pin(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } else if (ERROR_PIN_MODE_BIDIR == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Bidi error(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } + + return 0; + } + + if (argc == 1) + { + uint32_t x; + + x=abs(atol(argv[0])); + if (x<=3) + { + + SystemParams_t systemParams; + + memcpy(&systemParams,&NVM->SystemParams, sizeof(systemParams) ); + + systemParams.errorPinMode=(ErrorPinMode_t)x; + + nvmWriteSystemParms(systemParams); + stepperCtrl.updateParamsFromNVM(); + + if (ERROR_PIN_MODE_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Enable Active High(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + }else if (ERROR_PIN_MODE_ACTIVE_LOW_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Enable active low(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + }else if (ERROR_PIN_MODE_ERROR == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Error pin(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } else if (ERROR_PIN_MODE_BIDIR == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Error pin - Bidi error(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } + return 0; + + } + } + CommandPrintf(ptrUart, "use 'errorpinmode 0' for enable active high, 'errorpinmode 1' for enable active low and 'errorpinmode 2' for error output" ); + + + return 1; +} +#else +static int enablepinmode_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + bool ret; + + if (argc == 0) + { + if (ERROR_PIN_MODE_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Enable pin - Enable Active High(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + }else if (ERROR_PIN_MODE_ACTIVE_LOW_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Enable pin - Enable active low(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } else if (ERROR_PIN_MODE_BIDIR == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Enable pin - Bidi error(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } else + { + CommandPrintf(ptrUart,"UNDEFINED Pin Mode error(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } + + return 0; + } + + if (argc == 1) + { + uint32_t x; + + x=abs(atol(argv[0])); + + if (x<=1) + { + + SystemParams_t systemParams; + + memcpy(&systemParams,&NVM->SystemParams, sizeof(systemParams) ); + + systemParams.errorPinMode=(ErrorPinMode_t)x; + + nvmWriteSystemParms(systemParams); + stepperCtrl.updateParamsFromNVM(); + + if (ERROR_PIN_MODE_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Enable pin - Enable Active High(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + }else if (ERROR_PIN_MODE_ACTIVE_LOW_ENABLE == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Enable pin - Enable active low(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + }else if (ERROR_PIN_MODE_BIDIR == NVM->SystemParams.errorPinMode) + { + CommandPrintf(ptrUart,"Enable pin - Bidi error(%d)\n\r",(uint32_t)NVM->SystemParams.errorPinMode); + } + return 0; + + } + } + CommandPrintf(ptrUart, "use 'enablepinmode 0' for enable active high, 'enablepinmode 1' for enable active low " ); + + + return 1; +} +#endif + +static int factoryreset_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + nvmErase(); //erase all of the flash + NVIC_SystemReset(); +} +static int velocity_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + int64_t x; + + if (1 == argc) + { + float rpm; + rpm=atof(argv[0]); + x=(int64_t)(DIVIDE_WITH_ROUND(rpm*ANGLE_STEPS,60)); //divide with r + + + stepperCtrl.setVelocity(x); + } + int64_t y; + x=(stepperCtrl.getVelocity()*100 *60)/(ANGLE_STEPS); + y=abs(x-((x/100)*100)); + CommandPrintf(ptrUart,"Velocity is %d.%02d - %d\n\r",(int32_t)(x/100),(int32_t)y,(int32_t)stepperCtrl.getVelocity()); + + return 0; +} + +// +//static int printdata_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +//{ +// int32_t x; +// +// stepperCtrl.printData(); +// +// return 0; +//} + + +static int move_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + int32_t x,ma; + //CommandPrintf(ptrUart, "Move %d",argc); + + if (1 == argc) + { + float f; + + f=atof(argv[0]); + // if (f>1.8) + // f=1.8; + // if (f<-1.8) + // f=-1.8; + x=ANGLE_FROM_DEGREES(f); + LOG("moving %d", x); + + stepperCtrl.moveToAbsAngle(x); + } + if (2 == argc) + { + float f,rpm,a,y; + float pos,dx; + + f=atof(argv[0]); + rpm=atof(argv[1]); + // if (f>1.8) + // f=1.8; + // if (f<-1.8) + // f=-1.8; + + SmartPlanner.moveConstantVelocity(f,rpm); + return 0; + a=360*rpm/60/1000; //rotations/100ms + + pos=ANGLE_T0_DEGREES(stepperCtrl.getCurrentAngle()); + y=pos; + if (y>f) a=-a; + +#ifndef MECHADUINO_HARDWARE + SerialUSB.println(f); + SerialUSB.println(y); + SerialUSB.println(a); +#endif + + while (abs(y-f)>(2*abs(a))) + { + // SerialUSB.println(); + // SerialUSB.println(f); + // SerialUSB.println(y); + // SerialUSB.println(a); + y=y+a; + + x=ANGLE_FROM_DEGREES(y); + //LOG("moving %d", x); + stepperCtrl.moveToAbsAngle(x); + delay(1); + //y=stepperCtrl.getCurrentAngle(); + } + x=ANGLE_FROM_DEGREES(f); + LOG("moving %d", x); + stepperCtrl.moveToAbsAngle(x); + } + + return 0; +} + +static int boot_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + initiateReset(250); +} + +/* +static int microsteperror_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + int i,n,j; + bool feedback=stepperCtrl.getFeedback(); + n=200*stepperCtrl.getMicroSteps(); + + CommandPrintf(ptrUart, "Function needs fixed"); + return 0; + stepperCtrl.feedback(false); + for (j=0; j<2; j++) + { + for (i=0; iSystemParams.microsteps); +// CommandPrintf(ptrUart,"dirPinRotation %d\n\r",NVM->SystemParams.dirPinRotation); +// CommandPrintf(ptrUart,"errorLimit %d\n\r",NVM->SystemParams.errorLimit); +// CommandPrintf(ptrUart,"errorPinMode %d\n\r",NVM->SystemParams.errorPinMode); +// CommandPrintf(ptrUart,"controllerMode %d\n\r",NVM->SystemParams.controllerMode); +// +// } else if (5 == argc) +// { +// int32_t x; +// SystemParams_t systemParams; +// +// systemParams.microsteps=atol(argv[0]); +// x=atol(argv[1]); +// systemParams.dirPinRotation=CCW_ROTATION; +// if (x==0) +// { +// systemParams.dirPinRotation=CW_ROTATION; +// } +// systemParams.errorLimit=atol(argv[2]); +// systemParams.errorPinMode=(ErrorPinMode_t)atol(argv[3]); +// systemParams.controllerMode=(feedbackCtrl_t)atol(argv[4]); +// +// nvmWriteSystemParms(systemParams); +// stepperCtrl.updateParamsFromNVM(); +// +// CommandPrintf(ptrUart,"microsteps %d\n\r",NVM->SystemParams.microsteps); +// CommandPrintf(ptrUart,"dirPinRotation %d\n\r",NVM->SystemParams.dirPinRotation); +// CommandPrintf(ptrUart,"errorLimit %d\n\r",NVM->SystemParams.errorLimit); +// CommandPrintf(ptrUart,"errorPinMode %d\n\r",NVM->SystemParams.errorPinMode); +// CommandPrintf(ptrUart,"controllerMode %d\n\r",NVM->SystemParams.controllerMode); +// } else +// { +// CommandPrintf(ptrUart, "try 'sysparams microsteps dirPinRotation errorLimit errorPinMode controllerMode'\n\r\tlike 'sysparams 16 0 327 0 2'\n\e"); +// } +// return 0; +//} + +/* +static int motorparams_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (0 == argc) + { + CommandPrintf(ptrUart,"currentMa %d\n\r",NVM->motorParams.currentMa); + CommandPrintf(ptrUart,"currentHoldMa %d\n\r",NVM->motorParams.currentHoldMa); + CommandPrintf(ptrUart,"motorWiring %d\n\r",NVM->motorParams.motorWiring); + CommandPrintf(ptrUart,"fullStepsPerRotation %d\n\r",NVM->motorParams.fullStepsPerRotation); + + } else if (4 == argc) + { + int32_t x; + MotorParams_t motorParams; + + motorParams.currentMa=atol(argv[0]); + motorParams.currentHoldMa=atol(argv[1]); + motorParams.motorWiring=atol(argv[2]); + motorParams.fullStepsPerRotation=atol(argv[3]); + + nvmWriteMotorParms(motorParams); + stepperCtrl.updateParamsFromNVM(); + + CommandPrintf(ptrUart,"currentMa %d\n\r",NVM->motorParams.currentMa); + CommandPrintf(ptrUart,"currentHoldMa %d\n\r",NVM->motorParams.currentHoldMa); + CommandPrintf(ptrUart,"motorWiring %d\n\r",NVM->motorParams.motorWiring); + CommandPrintf(ptrUart,"fullStepsPerRotation %d\n\r",NVM->motorParams.fullStepsPerRotation); + } else + { + CommandPrintf(ptrUart, "try 'motorparams currentMa currentHoldMa motorWiring fullStepsPerRotation'\n\r\tlike 'motroparams 2200 1500 0 200'\n\e"); + } + return 0; +} + */ +static int vpid_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + CommandPrintf(ptrUart, "args %d\n\r",argc); + if (0 == argc) + { + int32_t x,y; + x=(int32_t)NVM->vPID.Kp; + y=abs(1000*NVM->vPID.Kp-(x*1000)); + CommandPrintf(ptrUart,"Kp %d.%03d\n\r",x,y); + + x=(int32_t)NVM->vPID.Ki; + y=abs(1000*NVM->vPID.Ki-(x*1000)); + CommandPrintf(ptrUart,"Ki %d.%03d\n\r",x,y); + + x=(int32_t)NVM->vPID.Kd; + y=abs(1000*NVM->vPID.Kd-(x*1000)); + CommandPrintf(ptrUart,"Kd %d.%03d\n\r",x,y); + } + if (3 == argc) + { + float Kp,Ki,Kd; + int32_t x,y; + + Kp=atof(argv[0]); + Ki=atof(argv[1]); + Kd=atof(argv[2]); + + nvmWrite_vPID(Kp,Ki,Kd); + stepperCtrl.updateParamsFromNVM(); //force the controller to use the new parameters + + x=(int32_t)NVM->vPID.Kp; + y=abs(1000*NVM->vPID.Kp-(x*1000)); + CommandPrintf(ptrUart,"Kp %d.%03d\n\r",x,y); + + x=(int32_t)NVM->vPID.Ki; + y=abs(1000*NVM->vPID.Ki-(x*1000)); + CommandPrintf(ptrUart,"Ki %d.%03d\n\r",x,y); + + x=(int32_t)NVM->vPID.Kd; + y=abs(1000*NVM->vPID.Kd-(x*1000)); + CommandPrintf(ptrUart,"Kd %d.%03d\n\r",x,y); + } + return 0; +} + +static int ppid_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (0 == argc) + { + int32_t x,y; + x=(int32_t)NVM->pPID.Kp; + y=abs(1000*NVM->pPID.Kp-(x*1000)); + CommandPrintf(ptrUart,"Kp %d.%03d\n\r",x,y); + + x=(int32_t)NVM->pPID.Ki; + y=abs(1000*NVM->pPID.Ki-(x*1000)); + CommandPrintf(ptrUart,"Ki %d.%03d\n\r",x,y); + + x=(int32_t)NVM->pPID.Kd; + y=abs(1000*NVM->pPID.Kd-(x*1000)); + CommandPrintf(ptrUart,"Kd %d.%03d\n\r",x,y); + } + if (3 == argc) + { + float Kp,Ki,Kd; + int32_t x,y; + + Kp=atof(argv[0]); + Ki=atof(argv[1]); + Kd=atof(argv[2]); + + nvmWrite_pPID(Kp,Ki,Kd); + stepperCtrl.updateParamsFromNVM(); //force the controller to use the new parameters + + x=(int32_t)NVM->pPID.Kp; + y=abs(1000*NVM->pPID.Kp-(x*1000)); + CommandPrintf(ptrUart,"Kp %d.%03d\n\r",x,y); + + x=(int32_t)NVM->pPID.Ki; + y=abs(1000*NVM->pPID.Ki-(x*1000)); + CommandPrintf(ptrUart,"Ki %d.%03d\n\r",x,y); + + x=(int32_t)NVM->pPID.Kd; + y=abs(1000*NVM->pPID.Kd-(x*1000)); + CommandPrintf(ptrUart,"Kd %d.%03d\n\r",x,y); + } + return 0; +} + +static int spid_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (0 == argc) + { + int32_t x,y; + x=(int32_t)NVM->sPID.Kp; + y=abs(1000*NVM->sPID.Kp-(x*1000)); + CommandPrintf(ptrUart,"Kp %d.%03d\n\r",x,y); + + x=(int32_t)NVM->sPID.Ki; + y=abs(1000*NVM->sPID.Ki-(x*1000)); + CommandPrintf(ptrUart,"Ki %d.%03d\n\r",x,y); + + x=(int32_t)NVM->sPID.Kd; + y=abs(1000*NVM->sPID.Kd-(x*1000)); + CommandPrintf(ptrUart,"Kd %d.%03d\n\r",x,y); + } + if (3 == argc) + { + float Kp,Ki,Kd; + int32_t x,y; + + Kp=atof(argv[0]); + Ki=atof(argv[1]); + Kd=atof(argv[2]); + + nvmWrite_sPID(Kp,Ki,Kd); + stepperCtrl.updateParamsFromNVM(); //force the controller to use the new parameters + + x=(int32_t)NVM->sPID.Kp; + y=abs(1000*NVM->sPID.Kp-(x*1000)); + CommandPrintf(ptrUart,"Kp %d.%03d\n\r",x,y); + + x=(int32_t)NVM->sPID.Ki; + y=abs(1000*NVM->sPID.Ki-(x*1000)); + CommandPrintf(ptrUart,"Ki %d.%03d\n\r",x,y); + + x=(int32_t)NVM->sPID.Kd; + y=abs(1000*NVM->sPID.Kd-(x*1000)); + CommandPrintf(ptrUart,"Kd %d.%03d\n\r",x,y); + } + return 0; +} + +static int torque_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (0 == argc) + { + CommandPrintf(ptrUart,"torque %d\n\r", stepperCtrl.getTorque()); + } + else if (1 == argc) + { + int32_t rec32; + int8_t rec; + rec32 = atoi(argv[0]); + if(rec32 > 127 || rec32 < -128) + { + CommandPrintf(ptrUart, "Error setting torque %d: not in valid range [-128, 127].", rec); + } + else + { + rec = (int8_t)rec32; + if (0 == rec) + { + torqueSetToZeroSpecialBehaviour(); + stepperCtrl.setTorque(0); // zero torque - used for monitoring purposes (added by vmario) + if (stepperCtrl.getControlMode() == CTRL_POS_PID) + { + CommandPrintf(ptrUart,"controller Current-Position-PID(3)"); + } + else if (stepperCtrl.getControlMode() == CTRL_SIMPLE) + { + CommandPrintf(ptrUart,"controller Simple-Position-PID(2)"); + } + } + else + { + stepperCtrl.setTorque(rec); // Units -128 - 127 + CommandPrintf(ptrUart, "torque set to %d", rec); + stepperCtrl.stealthSwitchMode(CTRL_TORQUE); + } + } + } + return 0; +} + +static int encoderdiag_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + char str[512]; + stepperCtrl.encoderDiagnostics(str); + CommandPrintf(ptrUart,"%s",str); + return 0; +} + +static int readpos_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + float pos; + int32_t x,y; + + pos=ANGLE_T0_DEGREES(stepperCtrl.getCurrentAngle()); + x=int(pos); + y=abs((pos-x)*100); + CommandPrintf(ptrUart,"encoder %d.%02d",x,y); + return 0; +} +static int feedback_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (0 == argc) + { + CommandPrintf(ptrUart,"must pass argument, 'feedback 0' - disables, 'feedback 1' - enables"); + return 1; + } + stepperCtrl.feedback(atoi(argv[0])); + return 0; +} + +static int step_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + if (argc == 0 ) + { + stepperCtrl.move(0, 1); + //stepperCtrl.step(STEPPER_FORWARD); + }else + { + int d, steps=1; + d=atoi(argv[0]); + if (argc >1) + { + steps=atoi(argv[1]); + } + if (1 == d) + { + stepperCtrl.move(1, steps); + } else + { + stepperCtrl.move(0, steps); + } + } + return 0; +} + + +static int microsteps_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + bool ret; + + if (argc != 1) + { + CommandPrintf(ptrUart,"microsteps %d\n\r",NVM->SystemParams.microsteps); + return 0; + } + + int32_t x; + + x=atol(argv[0]); + if (isPowerOfTwo(x) && x>0 && x<=256) + { + SystemParams_t systemParams; + + memcpy(&systemParams,&NVM->SystemParams, sizeof(systemParams) ); + + systemParams.microsteps=atol(argv[0]); + + nvmWriteSystemParms(systemParams); + stepperCtrl.updateParamsFromNVM(); + + CommandPrintf(ptrUart,"microsteps %d\n\r",NVM->SystemParams.microsteps); + + }else + { + CommandPrintf(ptrUart,"number of microsteps must be a power of 2 between 1 and 256"); + return 1; //return error + } + + return 0; +} + + +// print out the help strings for the commands +static int help_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + sCommand cmd_list; + int i; + + //now let's parse the command + i=0; + memcpy(&cmd_list, &Cmds[i], sizeof(sCommand)); + while(cmd_list.function!=0) + { + + CommandPrintf(ptrUart,(cmd_list.name)); + CommandPrintf(ptrUart,(" - ")); + CommandPrintf(ptrUart,(cmd_list.help)); + CommandPrintf(ptrUart,("\n\r")); + i=i+1; + memcpy(&cmd_list, &Cmds[i], sizeof(sCommand)); + } + return 0; +} + + + +static int getcal_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + stepperCtrl.calTable.printCalTable(); + return 0; +} + +static int calibrate_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + stepperCtrl.calibrateEncoder(); + CommandPrintf(ptrUart,"Calibration DONE!\n\r"); + return 0; +} + +static int testcal_cmd(sCmdUart *ptrUart,int argc, char * argv[]) +{ + Angle a; + int32_t x; + + a=stepperCtrl.maxCalibrationError(); + x=(uint16_t)a*(int32_t)360000L/(int32_t)ANGLE_MAX; + + CommandPrintf(ptrUart,"Max error is %d.%03d degrees\n\r", x/1000,abs(x)%1000); + return 0; +} + + +#ifndef MECHADUINO_HARDWARE + +uint8_t kbhit(void) +{ + return SerialUSB.available(); + //return SerialUSB.peek() != -1; +} +uint8_t getChar(void) +{ + return SerialUSB.read(); +} +uint8_t putch(char data) +{ + return SerialUSB.write((uint8_t)data); +} + +#endif +uint8_t kbhit_hw(void) +{ + return Serial5.available(); + //return SerialUSB.peek() != -1; +} +uint8_t getChar_hw(void) +{ + return Serial5.read(); +} +uint8_t putch_hw(char data) +{ + return Serial5.write((uint8_t)data); +} + + +uint8_t kbhit_step_dir(void) +{ + return Serial1.available(); + //return SerialUSB.peek() != -1; +} +uint8_t getChar_step_dir(void) +{ + return Serial1.read(); +} +uint8_t putch_step_dir(char data) +{ + return Serial1.write((uint8_t)data); +} + + + +void commandsInit(void) +{ + +#ifndef MECHADUINO_HARDWARE + CommandInit(&UsbUart, kbhit, getChar, putch ,NULL); //set up the UART structure + SerialUSB.print("\n\rPower Up\n\r"); + SerialUSB.print(COMMANDS_PROMPT); +#endif + + CommandInit(&HostUart, kbhit_step_dir, getChar_step_dir, putch_step_dir ,NULL); //set up the UART structure for step and dir pins + +#ifdef CMD_SERIAL_PORT + CommandInit(&SerialUart, kbhit_hw, getChar_hw, putch_hw ,NULL); //set up the UART structure + Serial5.print("\n\rPower Up\n\r"); + Serial5.print(COMMANDS_PROMPT); +#endif + +} + +int commandsProcess(void) +{ +#ifdef USE_STEP_DIR_SERIAL + //if the step pin is configured to the SerialCom 0 then we need to process commands + //if PA11 (D0) is configured to perpherial C then the step pin is UART + if (getPinMux(PIN_STEP_INPUT) == PORT_PMUX_PMUXE_C_Val) + { + //SerialUSB.println("host"); + CommandProcess(&HostUart,Cmds,' ',COMMANDS_PROMPT); + } +#endif //USE_STEP_DIR_SERIAL + + +#ifdef CMD_SERIAL_PORT + CommandProcess(&SerialUart,Cmds,' ',COMMANDS_PROMPT); +#endif + +#ifndef MECHADUINO_HARDWARE +if (SerialUSB.dtr()) + { + return CommandProcess(&UsbUart,Cmds,' ',COMMANDS_PROMPT); + } +#endif +} + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/commands.h b/firmware_smartstepper_trikarus/stepper_nano_zero/commands.h new file mode 100644 index 0000000..3edef45 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/commands.h @@ -0,0 +1,51 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __COMMANDS_H__ +#define __COMMANDS_H__ +#include +#include "stepper_controller.h" +#include "nzs.h" + +extern StepperCtrl stepperCtrl; +extern eepromData_t PowerupEEPROM; + +void commandsInit(void); +int commandsProcess(void); +void torqueSetToZeroSpecialBehaviour(void); + +#endif //__COMMANDS_H__ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.cpp new file mode 100644 index 0000000..e82b3fb --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.cpp @@ -0,0 +1,309 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "eeprom.h" +#include "calibration.h" +#include "Flash.h" +#include "board.h" //for divide with rounding macro +#include +#include "syslog.h" + +//since we will write the following structure into each page, we need to find our latest page +// to do this we will use the header to contain a checksum and write counter. +#define EEPROM_SIZE (FLASH_ROW_SIZE*2) + +typedef struct { + uint16_t checksum; + uint16_t count; +}eepromHeader_t; + +#define EEPROM_DATA_SIZE (FLASH_PAGE_SIZE_NZS-sizeof(eepromHeader_t)) +typedef struct { + eepromHeader_t header; + uint8_t data[EEPROM_DATA_SIZE]; +} eepromData_t; + + + +static eepromData_t EEPROMCache; + +static int32_t NextPageWrite=-1; + +//we need to reserve two pages for EEPROM +__attribute__((__aligned__(FLASH_ROW_SIZE))) const uint8_t NVM_eeprom[EEPROM_SIZE]={0xFF}; + + +static uint16_t checksum(uint8_t *ptrData, uint32_t nBytes) +{ + uint16_t sum=0; + uint32_t i; + i=0; + //LOG("running checksum %d",nBytes); + while(idata, EEPROM_DATA_SIZE); + //LOG("checksum is %d %d",cs,ptrData->header.checksum); + + if (cs==ptrData->header.checksum) + { + //LOG("Page good %d",page); + return true; + } + //LOG("page bad %d",page); + return false; +} + +static void printEEPROM(uint32_t page) +{ + eepromData_t *ptrData; + int i; + ptrData=(eepromData_t *)&NVM_eeprom[page]; + LOG("count %d", ptrData->header.count); + LOG("checksum %d", ptrData->header.checksum); + for (i=0; i<10; i++) + { + LOG("Data[%d]=%02X",i,ptrData->data[i]); + } +} + +static uint32_t findLastGoodPage(void) +{ + uint32_t lastGoodPage=0; + uint32_t page; + uint16_t lastCnt=0; + eepromData_t *ptrData; + + page=0; + while(page < (EEPROM_SIZE)) + { + //LOG("checking page %d",page); + if (isPageGood(page)) + { + ptrData=(eepromData_t *)&NVM_eeprom[page]; + + //check for roll over which is OK + if (lastCnt==16534 && ptrData->header.count==1) + { + lastCnt=ptrData->header.count; + lastGoodPage=page; + } + if (ptrData->header.count>lastCnt) + { + //make sure we have not rolled over. + if ((ptrData->header.count-lastCnt)<(16534/2)) + { + lastCnt=ptrData->header.count; + lastGoodPage=page; + } + } + } + page=page + FLASH_PAGE_SIZE_NZS; + } + //LOG("last good page %d",lastGoodPage); + return lastGoodPage; +} + +//find the next page to write +static uint32_t eepromGetNextWritPage(void) +{ + eepromHeader_t *ptrHeader; + uint32_t page; + uint32_t row; + int blockCount; + int done=0; + + //start at first address: + page=0; + + while(page < (EEPROM_SIZE)) + { + //LOG("checking page %d",page); + ptrHeader=(eepromHeader_t *) &NVM_eeprom[page]; + if (ptrHeader->count == 0xFFFF) + { + uint32_t i; + uint8_t *ptrData; + //uint8_t erasedByte=(uint8_t)ptrHeader->count; + bool erased=true; + + //verify page is erased + ptrData= (uint8_t *)&NVM_eeprom[page]; + + for (i=0; i=EEPROM_SIZE) + { + row=0; + //TODO we should make sure this not where good data is + // however if it is what should we do? + } + + //now we need to erase that row + //WARNING("Erasing page %d",row*FLASH_ROW_SIZE); + flashErase(&NVM_eeprom[row*FLASH_ROW_SIZE],FLASH_ROW_SIZE); + page=row*FLASH_ROW_SIZE; + //LOG("Next free page is %d",page); + return page; +} + + +eepromError_t eepromInit(void) +{ + uint32_t page; + + + //find the last good page offset in flash + page=findLastGoodPage(); + LOG("EEPROM Init found page %d",page); + if (isPageGood(page)) + { + LOG("EEPROM page good %d",page); + memcpy(&EEPROMCache, &NVM_eeprom[page], sizeof(EEPROMCache)); + + NextPageWrite=eepromGetNextWritPage(); + return EEPROM_OK; + } + //ERROR("page is bad"); + memset(&EEPROMCache, 0, sizeof(EEPROMCache)); + NextPageWrite=eepromGetNextWritPage(); + return EEPROM_CORRUPT; +} + + +int eepromWriteCache(uint8_t *ptrData, uint32_t size) +{ + //LOG("Cache write %d",size); + if (NextPageWrite==-1) //some one did not init the module + { + //lets handle gracefully and do it ourselves + eepromInit(); + } + if (size>EEPROM_DATA_SIZE) + { + size =EEPROM_DATA_SIZE; + } + memcpy(EEPROMCache.data, ptrData, size); + EEPROMCache.header.checksum=checksum(EEPROMCache.data,EEPROM_DATA_SIZE); + + + return size; +} + +int eepromRead(uint8_t *ptrData, uint32_t size) //returns number of bytes actually read, whcih could be less than size requested +{ + if (NextPageWrite==-1) //some one did not init the module + { + //lets handle gracefully and do it ourselves + eepromInit(); + } + if (size>EEPROM_DATA_SIZE) + { + size =EEPROM_DATA_SIZE; + } + if (EEPROMCache.header.count == 0) + { + return 0; //cache is new/corrupt + } + memcpy(ptrData, EEPROMCache.data, size); + return size; +} + +eepromError_t eepromFlush(void) //flush the cache to flash memory +{ + if (NextPageWrite==-1) + { + ERROR("EEPROM WRITE FAILED"); + return EEPROM_FAILED; //most likely no one has written to cache + } + EEPROMCache.header.count++; + if (EEPROMCache.header.count>=16535) + { + EEPROMCache.header.count=1; + } + //WARNING("Writting to Page %d",NextPageWrite); + flashWrite(&NVM_eeprom[NextPageWrite], &EEPROMCache, sizeof(EEPROMCache)); + + // printEEPROM(NextPageWrite); + + if (!SYSCTRL->PCLKSR.bit.BOD33DET) //if not in brown out condition find next write location + { + //LOG("getting next page to write"); + NextPageWrite=eepromGetNextWritPage(); //find next write location and erase if needed + } else + { + //LOG("BOD active"); + NextPageWrite=-1; //else we will just clear NextPageWrite location just in case we recover from brown out + } + return EEPROM_OK; +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.h b/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.h new file mode 100644 index 0000000..75154eb --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.h @@ -0,0 +1,62 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef EEPROM_H_ +#define EEPROM_H_ +#include "Flash.h" +#include "calibration.h" +#include "board.h" + +/* + * This EEPROM implementation provides 60bytes of "eeprom space" (we reserve 4 bytes for overhead) + * The EEPROM uses two rows of flash (256 bytes per row), which + * for the SAMD21G18A this allows a minimual 200k writes, but typically 1200k + */ + +typedef enum { + EEPROM_OK =0, + EEPROM_FAILED=1, + EEPROM_CORRUPT=2, +} eepromError_t; + + +eepromError_t eepromInit(void); +int eepromWriteCache(uint8_t *ptrData, uint32_t size); //returns number bytes written to cache +eepromError_t eepromFlush(void); //flush the cache to flash memory +int eepromRead(uint8_t *ptrData, uint32_t size); //returns number of bytes actually read, whcih could be less than size requested + +#endif /* EEPROM_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.cpp new file mode 100644 index 0000000..cfe9b4e --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.cpp @@ -0,0 +1,1685 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "fet_driver.h" +#include "wiring_private.h" +#include "syslog.h" +#include "angle.h" +#include "Arduino.h" +#include "sine.h" +#include "nonvolatile.h" + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + +#ifdef NEMA_23_10A_HW + +#define FET_DRIVER_FREQ (46875UL) //FET PWM pin driver frequency + +FetDriver *FetDriver::ptrInstance=0; + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncDAC() __attribute__((always_inline, unused)); +static void syncDAC() { + while (DAC->STATUS.bit.SYNCBUSY == 1) + ; +} + + +volatile uint32_t coilA_Value=0; +/* + * The discrete FETs on the NEMA 23 10A board are configured such that each H-bridge has: + * IN1 - Input 1 + * IN2 - Input 2 + * Enable - Enable driver + * Isense - current sense + * + * The truth table for the H-Bridge is: + * Enable IN1 IN2 Bridge State + * 0 x x floating (FETs off) + * 1 0 0 coil shorted to Gnd + * 1 0 1 forward + * 1 1 0 reverse + * 1 1 1 coil shorted to VCC + * + * For peak current control there is two state (fast decay, and slow decay) + * + * Fast Decay + * When driving coil in forward direction and current peak is reached the fast decay turns + * The bridge in the reverse direction. This cause the reverse EMF from coil to charge + * capacitors back up and the current on the coil to drop very quickly + * + * Slow Decay + * During this mode the current decay is slower by shorting the coil leads to ground. + * This in effect shorts the coil leads and reverse EMF is converted to heat. + * + * In the Fast Decay mode we reverse the motor, this in effect is trying to drive coil + * current in the reverse direction. This in effect reduces current faster than just + * shorting the coil out. + * + * see www.misfittech.net's blog for more information on this subject + * + */ + +/* driver code's logic + * + * This driver code needs not only to control the FETs but also handle the current limits. + * + * The way the code handles limiting current is by using two comparators internal to + * the microprocessor. + * + * We first use two PWM signals to generate reference voltage for each comparator. + * Then when the current sense voltage exceeds this reference voltage an interrupt is + * generated. In the interrupt handler we will then set the decay mode as needed. + * + * It will have to be determined if we will use a fixed time decay mode like the A4954, + * or use current as the threshold. There is a lot to do here to maintain quite operation, + * that is we need this current control to be running at more than 20khz to be quite. + * + * Additionally we can use ADC on the current sense for detecting the flyback and + * get some idea of the inductance. This can be used for stall dection as well as + * auto tuning of some of the driver parameters. + */ + + + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + +#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY); + +typedef enum { + CURRENT_ON = 0, + CURRENT_FAST_DECAY = 1, + CURRENT_SLOW_DECAY = 2, +} CurrentMode_t; + +typedef enum { + COIL_FORWARD =0, + COIL_REVERSE =1, + COIL_BRAKE =2 +} CoilState_t; + +typedef struct { + bool currentIncreasing; //true when we are increasing current + CurrentMode_t currentState; //how is bridge driven +} BridgeState_t; + +volatile BridgeState_t BridgeA, BridgeB; + + +#define DAC_MAX (0x01FFL) +// Wait for synchronization of registers between the clock domains +static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused)); +static void syncTCC(Tcc* TCCx) { + //int32_t t0=1000; + while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK) + { + // t0--; + // if (t0==0) + // { + // break; + // } + + } +} + + + + + +static inline void coilA(CoilState_t state) +{ + PIN_GPIO_OUTPUT(PIN_FET_IN1); + PIN_GPIO_OUTPUT(PIN_FET_IN2); + switch(state){ + + case COIL_FORWARD: + GPIO_HIGH(PIN_FET_IN1); + GPIO_LOW(PIN_FET_IN2); + break; + + case COIL_REVERSE: + GPIO_HIGH(PIN_FET_IN2); + GPIO_LOW(PIN_FET_IN1); + break; + + case COIL_BRAKE: + GPIO_LOW(PIN_FET_IN2); + GPIO_LOW(PIN_FET_IN1); + break; + + default: + ERROR("Not a known state"); + break; + } + +} + +static inline void coilB(CoilState_t state) +{ + PIN_GPIO_OUTPUT(PIN_FET_IN3); + PIN_GPIO_OUTPUT(PIN_FET_IN4); + switch(state){ + case COIL_FORWARD: + GPIO_HIGH(PIN_FET_IN3); + GPIO_LOW(PIN_FET_IN4); + break; + + case COIL_REVERSE: + GPIO_HIGH(PIN_FET_IN4); + GPIO_LOW(PIN_FET_IN3); + break; + + case COIL_BRAKE: + GPIO_LOW(PIN_FET_IN3); + GPIO_LOW(PIN_FET_IN4); + break; + + default: + ERROR("Not a known state"); + break; + } +} + + +int FetDriver::coilA_PWM(int32_t value) +{ + int32_t x; + // PIN_FET_IN1 (PA15) (5) (TCC0 WO[5], aka ch1) + //PIN_FET_IN2 (PA20) (6) (TCC0 WO[6], aka ch2) + Tcc* TCCx = TCC0 ; + +// +// if (value==0) +// { +// GPIO_LOW(PIN_FET_IN1); +// GPIO_LOW(PIN_FET_IN2); +// PIN_GPIO(PIN_FET_IN1); +// PIN_GPIO(PIN_FET_IN2); +// return; +// } + + if (value<0) + { + GPIO_LOW(PIN_FET_IN1); + PIN_GPIO(PIN_FET_IN1); + PIN_PERIPH(PIN_FET_IN2); + //pinPeripheral(PIN_FET_IN2, PIO_TIMER_ALT); //TCC0 WO[7] + value=-value; + }else + { + GPIO_LOW(PIN_FET_IN2); + PIN_GPIO(PIN_FET_IN2); + PIN_PERIPH(PIN_FET_IN1); + //pinPeripheral(PIN_FET_IN1, PIO_TIMER_ALT); + } + + +#if (F_CPU/FET_DRIVER_FREQ)==1024 + x=value & 0x3FF; +#else + x=MIN(value, (int32_t)(F_CPU/FET_DRIVER_FREQ)); +#endif + + syncTCC(TCCx); + TCCx->CC[1].reg = (uint32_t)x; //ch1 == ch5 //IN3 + //syncTCC(TCCx); + TCCx->CC[2].reg = (uint32_t)x; //ch2 == ch6 //IN4 + if (x!=value) + { + return 1; + } + return 0; + +} + +void FetDriver::coilB_PWM(int32_t value) +{ + + //PIN_FET_IN3 (PA21) (7) (TCC0 WO[7], aka ch3) + //PIN_FET_IN4 (PA14) (2) (TCC0 WO[4], aka ch0) + Tcc* TCCx = TCC0 ; + + +// +// if (value==0) +// { +// GPIO_LOW(PIN_FET_IN3); +// GPIO_LOW(PIN_FET_IN4); +// PIN_GPIO(PIN_FET_IN3); +// PIN_GPIO(PIN_FET_IN4); +// return; +// } + + + if (value<=0) + { + GPIO_LOW(PIN_FET_IN3); + PIN_GPIO(PIN_FET_IN3); + PIN_PERIPH(PIN_FET_IN4); + //SET_PIN_PERHERIAL(PIN_FET_IN4, PIO_TIMER_ALT); //TCC0 WO[7] + value=-value; + }else + { + GPIO_LOW(PIN_FET_IN4); + PIN_GPIO(PIN_FET_IN4); + PIN_PERIPH(PIN_FET_IN3); + //SET_PIN_PERHERIAL(PIN_FET_IN3, PIO_TIMER_ALT); + } + + +#if (F_CPU/FET_DRIVER_FREQ)==1024 + value=value & 0x3FF; +#else + value=MIN(value, (int32_t)(F_CPU/FET_DRIVER_FREQ)); +#endif + + //LOG("value is %d",value); + // if (value> 300) //(F_CPU/FET_DRIVER_FREQ)) + // { + // value= 300; //F_CPU/FET_DRIVER_FREQ; + // } + syncTCC(TCCx); + TCCx->CC[0].reg = (uint32_t)value; //ch0 == ch4 //IN4 + //syncTCC(TCCx); + TCCx->CC[3].reg = (uint32_t)value; //ch3 == ch7 //IN3 + + +} + +static void enableTCC0(void) +{ + Tcc* TCCx = TCC0 ; + + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; + + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + + //ERROR("Setting TCC %d %d",ulValue,ulPin); + TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + syncTCC(TCCx); + + // Set TCx as normal PWM + TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; + syncTCC(TCCx); + + // Set PER to maximum counter value (resolution : 0xFF) + TCCx->PER.reg = F_CPU/FET_DRIVER_FREQ; //set frequency to 100Khz + syncTCC(TCCx); + + // Enable TCCx + TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; + syncTCC(TCCx); + //ERROR("Enable TCC0 DONE"); + +} + +static void setDAC(uint32_t DAC1, uint32_t DAC2) +{ + TCC1->CC[1].reg = (uint32_t)DAC1; //D9 PA07 - VREF12 + syncTCC(TCC1); + TCC1->CC[0].reg = (uint32_t)DAC2; //D4 - VREF34 + syncTCC(TCC1); +} + + + +static void setupDAC(void) +{ + Tcc* TCCx = TCC1 ; + + + pinPeripheral(PIN_FET_VREF1, PIO_TIMER_ALT); + pinPeripheral(PIN_FET_VREF2, PIO_TIMER_ALT); + + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; + + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + + //ERROR("Setting TCC %d %d",ulValue,ulPin); + TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + syncTCC(TCCx); + + // Set TCx as normal PWM + TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; + syncTCC(TCCx); + + // Set TCx in waveform mode Normal PWM + TCCx->CC[1].reg = (uint32_t)0; + syncTCC(TCCx); + + TCCx->CC[0].reg = (uint32_t)0; + syncTCC(TCCx); + + // Set PER to maximum counter value (resolution : 0xFFF = 12 bits) + // =48e6/2^12=11kHz frequency + TCCx->PER.reg = DAC_MAX; + syncTCC(TCCx); + + // Enable TCCx + TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; + syncTCC(TCCx); + +} + + +/* + * The SAMD21 has two analog comparators + * COMP_FET_A(A4/PA05) and COMP_FET_B(D9/PA07) are the reference voltages + * + * ISENSE_FET_A(A3/PA04) and ISENSE_FET_B(D8/PA06) are the current sense + * + */ +/* +static void setupComparators(void) +{ + //setup the pins as analog inputs + pinPeripheral(COMP_FET_A, PIO_ANALOG); //AIN[1] + pinPeripheral(COMP_FET_B, PIO_ANALOG); //AIN[3] + pinPeripheral(ISENSE_FET_A, PIO_ANALOG); //AIN[0] + pinPeripheral(ISENSE_FET_B, PIO_ANALOG); //AIN[2] + + //enable the clock for the Analog comparator + PM->APBCMASK.reg |= PM_APBCMASK_AC; //enable clock in the power manager + + //setup the GCLK for the analog and digital clock to the AC + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_AC_ANA )) ; + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_AC_DIG )) ; + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + + + //we will drive the CMP0 and CMP1 high when our current is exceeded. + // To do this we will set ISense Pins as the non-inverting input + AC->CTRLA.reg=0x01; //disable AC_COMPCTRL_ENABLE and reset + while ( AC->STATUSB.bit.SYNCBUSY == 1 ) ; + AC->CTRLB.reg=0x0; // set start bits low (will not be used) + while ( AC->STATUSB.bit.SYNCBUSY == 1 ) ; + AC->COMPCTRL[0].reg = AC_COMPCTRL_FLEN_MAJ3_Val | //add a 3 bit majority digital filter + AC_COMPCTRL_HYST | //enable hysterisis + AC_COMPCTRL_MUXPOS_PIN0 | //non-inverting is AIN[0] + AC_COMPCTRL_MUXNEG_PIN1 | //inverting pin is AIN[1] + AC_COMPCTRL_INTSEL_RISING | //interrupt on the rising edge (TODO we might want on both edges) + AC_COMPCTRL_SPEED_HIGH | + AC_COMPCTRL_ENABLE; //set to high speed mode, we don't care about power consumption + while ( AC->STATUSB.bit.SYNCBUSY == 1 ) ; + AC->COMPCTRL[1].reg = //AC_COMPCTRL_FLEN_MAJ3_Val | //add a 3 bit majority digital filter + //AC_COMPCTRL_HYST | //enable hysterisis + AC_COMPCTRL_MUXPOS_PIN2 | //non-inverting is AIN[2] + AC_COMPCTRL_MUXNEG_PIN3 | //inverting pin is AIN[3] + AC_COMPCTRL_INTSEL_RISING | //interrupt on the rising edge (TODO we might want on both edges) + AC_COMPCTRL_SPEED_HIGH | + //AC_COMPCTRL_SWAP | + AC_COMPCTRL_ENABLE; //set to high speed mode, we don't care about power consumption + while ( AC->STATUSB.bit.SYNCBUSY == 1 ) ; + + //enable the comparator + AC->CTRLA.reg=AC_CTRLA_ENABLE; + while ( AC->STATUSB.bit.SYNCBUSY == 1 ); + + + + AC->INTENSET.bit.COMP0=1; + AC->INTENSET.bit.COMP1=1; + NVIC_EnableIRQ(AC_IRQn); //enable the comparator interrupt +} + */ + +static __inline__ void syncADC() __attribute__((always_inline, unused)); +static void syncADC() { + volatile int32_t t0=100; + while ((ADC->STATUS.bit.SYNCBUSY == 1))// && t0>0) + { + t0--; + if (t0>0) + { + break; + } + } + if (t0<=0) + { + ERROR("sync ADC timeout"); + } +} + + + + +static uint32_t ADCRead(uint32_t ulPin) +{ + uint32_t valueRead = 0; + uint32_t gainValue=0; + + if ( ulPin <= 5 ) // turn '0' -> 'A0' + { + ulPin += A0 ; + } + if (ulPin == 6) ulPin = PIN_A6; + if (ulPin == 7) ulPin = PIN_A7; + + pinPeripheral(PIN_A4, PIO_ANALOG); + + pinPeripheral(ulPin, PIO_ANALOG); + + syncADC(); + ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV32 | // Divide Clock by 512. + ADC_CTRLB_RESSEL_12BIT; // 10 bits resolution as default + // syncADC(); + // ADC->INPUTCTRL.reg = 0; + + // syncADC(); + // ADC->INPUTCTRL.bit.MUXNEG= ADC_INPUTCTRL_MUXNEG_GND;//g_APinDescription[ulPin].ulADCChannelNumber; //ADC_INPUTCTRL_MUXNEG_GND; + //ADC_INPUTCTRL_MUXNEG_IOGND; //ADC_INPUTCTRL_MUXNEG_PIN5; // No Negative input (Internal Ground) + + + syncADC(); + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber;//ADC_INPUTCTRL_MUXPOS_DAC;// g_APinDescription[ulPin].ulADCChannelNumber; // Selection for the positive ADC input + + + syncADC(); + ADC->INPUTCTRL.bit.GAIN = 0xF; //0x0F == gain of 1/2 + + syncADC(); + ADC->REFCTRL.reg=ADC_REFCTRL_REFSEL_INTVCC1; //set the ADC reference to 1/2VDDANA + + syncADC(); + ADC->SAMPCTRL.reg=0x02; + /* + * Bit 1 ENABLE: Enable + * 0: The ADC is disabled. + * 1: The ADC is enabled. + * Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The + * value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register + * (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete. + * + * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be + * configured. The first conversion after the reference is changed must not be used. + */ + + syncADC(); + ADC->CTRLA.bit.ENABLE = 0x01; // Enable ADC + + + // Clear the Data Ready flag + syncADC(); + ADC->INTFLAG.bit.RESRDY = 1; + // Start conversion + syncADC(); + ADC->SWTRIG.bit.START = 1; + + + // wait for conversion to be done + while ( ADC->INTFLAG.bit.RESRDY == 0 ); // Waiting for conversion to complete + + // Clear the Data Ready flag + syncADC(); + ADC->INTFLAG.bit.RESRDY = 1; + // Start conversion again, since The first conversion after the reference is changed must not be used. + syncADC(); + ADC->SWTRIG.bit.START = 1; + + while ( ADC->INTFLAG.bit.RESRDY == 0 ); // Waiting for conversion to complete + valueRead = ADC->RESULT.reg; + + // syncADC(); + // ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC + // syncADC(); + + return valueRead; //mapResolution(valueRead, _ADCResolution, _readResolution); + +} + +int32_t fastADCRead(uint32_t ulPin) +{ + int32_t valueRead; + if ( ulPin <= 5 ) // turn '0' -> 'A0' + { + ulPin += A0 ; + } + if (ulPin == 6) ulPin = PIN_A6; + if (ulPin == 7) ulPin = PIN_A7; + syncADC(); + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber;//ADC_INPUTCTRL_MUXPOS_DAC;// g_APinDescription[ulPin].ulADCChannelNumber; // Selection for the positive ADC input + // Clear the Data Ready flag + syncADC(); + ADC->INTFLAG.bit.RESRDY = 1; + // Start conversion again, since The first conversion after the reference is changed must not be used. + syncADC(); + ADC->SWTRIG.bit.START = 1; + + while ( ADC->INTFLAG.bit.RESRDY == 0 ); // Waiting for conversion to complete + valueRead = ADC->RESULT.reg; + return valueRead; +} + +int32_t GetMeanAdc(uint16_t pin, uint16_t samples) +{ + int32_t i=0; + int32_t mean=0; + int32_t adc; + while (i 'A0' + { + ulPin += A0 ; + } + if (ulPin == 6) ulPin = PIN_A6; + if (ulPin == 7) ulPin = PIN_A7; + + pinPeripheral(PIN_A4, PIO_ANALOG); + + pinPeripheral(ulPin, PIO_ANALOG); + + syncADC(); + ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV64 | // Divide Clock by 512. + ADC_CTRLB_RESSEL_12BIT; // 10 bits resolution as default + // syncADC(); + // ADC->INPUTCTRL.reg = 0; + + // syncADC(); + // ADC->INPUTCTRL.bit.MUXNEG= ADC_INPUTCTRL_MUXNEG_GND;//g_APinDescription[ulPin].ulADCChannelNumber; //ADC_INPUTCTRL_MUXNEG_GND; + //ADC_INPUTCTRL_MUXNEG_IOGND; //ADC_INPUTCTRL_MUXNEG_PIN5; // No Negative input (Internal Ground) + + syncADC(); + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ulPin].ulADCChannelNumber;//ADC_INPUTCTRL_MUXPOS_DAC;// g_APinDescription[ulPin].ulADCChannelNumber; // Selection for the positive ADC input + + syncADC(); + ADC->INPUTCTRL.bit.INPUTSCAN=0; + // + // switch (gain) + // { + // case 1: + // gainValue=ADC_INPUTCTRL_GAIN_1X_Val; + // break; + // case 2: + // gainValue=ADC_INPUTCTRL_GAIN_2X_Val; + // break; + // case 4: + // gainValue=ADC_INPUTCTRL_GAIN_4X_Val; + // break; + // case 8: + // gainValue=ADC_INPUTCTRL_GAIN_8X_Val; + // break; + // case 16: + // gainValue=ADC_INPUTCTRL_GAIN_16X_Val; + // break; + // default: + // gainValue=ADC_INPUTCTRL_GAIN_1X_Val; + // break; + // } + + // syncADC(); + // ADC->CTRLB.bit.DIFFMODE = 0; //set to differential mode + + syncADC(); + ADC->INPUTCTRL.bit.GAIN = 0xF; //0x0F == gain of 1/2 + + // syncADC(); + // ADC->AVGCTRL.reg=5; + + syncADC(); + ADC->REFCTRL.reg=ADC_REFCTRL_REFSEL_INTVCC1; //set the ADC reference to 1/2VDDANA + + syncADC(); + ADC->SAMPCTRL.reg=0x0F; + /* + * Bit 1 ENABLE: Enable + * 0: The ADC is disabled. + * 1: The ADC is enabled. + * Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The + * value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register + * (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete. + * + * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be + * configured. The first conversion after the reference is changed must not be used. + */ + syncADC(); + ADC->CTRLA.bit.ENABLE = 0x01; // Enable ADC + + + //Setup up for ISR + ADC->INTENCLR.reg=0x0F; + ADC->INTENSET.bit.RESRDY=1; + + NVIC_SetPriority(ADC_IRQn, 3); + + + // Clear the Data Ready flag + ADC->INTFLAG.bit.RESRDY = 1; + + // Start conversion + syncADC(); + ADC->SWTRIG.bit.START = 1; + + + + // Start conversion again, since The first conversion after the reference is changed must not be used. + //syncADC(); + //ADC->SWTRIG.bit.START = 1; + + //ADC->INTENSET.bit.RESRDY=1; + + // // Store the value + while ( ADC->INTFLAG.bit.RESRDY == 0 ); // Waiting for conversion to complete + // valueRead = ADC->RESULT.reg; + // + // syncADC(); + // ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC + // syncADC(); + + uint32_t reg; + + syncADC(); + reg=ADC->CTRLA.reg; + LOG("ADC CTRLA 0x%04X",reg); + + syncADC(); + reg=ADC->REFCTRL.reg; + LOG("ADC REFCTRL 0x%04X",reg); + + syncADC(); + reg=ADC->AVGCTRL.reg; + LOG("ADC AVGCTRL 0x%04X",reg); + + syncADC(); + reg=ADC->SAMPCTRL.reg; + LOG("ADC SAMPCTRL 0x%04X",reg); + + syncADC(); + reg=ADC->CTRLB.reg; + LOG("ADC CTRLB 0x%04X",reg); + + syncADC(); + reg=ADC->INPUTCTRL.reg; + LOG("ADC INPUTCTRL 0x%04X",reg); + + syncADC(); + reg=ADC->GAINCORR.reg; + LOG("ADC GAINCORR 0x%04X",reg); + + syncADC(); + reg=ADC->OFFSETCORR.reg; + LOG("ADC OFFSETCORR 0x%04X",reg); + + syncADC(); + reg=ADC->CALIB.reg; + LOG("ADC CALIB 0x%04X",reg); + + + // Enable InterruptVector + NVIC_EnableIRQ(ADC_IRQn); + + // Clear the Data Ready flag + ADC->INTFLAG.bit.RESRDY = 1; + + + // Start conversion + syncADC(); + ADC->SWTRIG.bit.START = 1; + + return 0;//valueRead; //mapResolution(valueRead, _ADCResolution, _readResolution); +} +void ADC_Handler(void) +{ + + uint16_t channel; + uint16_t value; + static uint16_t lastChannel=0; + + //static int state=0; + YELLOW_LED(1); + //state=(state+1)&0x01; + + value=ADC->RESULT.reg; + channel=ADC->INPUTCTRL.bit.MUXPOS;// + ADC->INPUTCTRL.bit.INPUTOFFSET; + + //LOG("channel is %d %d", lastChannel,value); + + FetDriver::ADC_Callback(lastChannel,value); + lastChannel=channel; + + if (channel == g_APinDescription[ISENSE_FET_B].ulADCChannelNumber) + { + syncADC(); + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ISENSE_FET_A].ulADCChannelNumber; + } else + { + syncADC(); + ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[ISENSE_FET_B].ulADCChannelNumber; + } + + //LOG("channel is %d %d", ADC->INPUTCTRL.bit.MUXPOS ,value); + //syncADC(); + ADC->INTFLAG.bit.RESRDY = 1; + //syncADC(); + ADC->SWTRIG.bit.START = 1; + YELLOW_LED(0); + //state=(state+1)&0x01; + +} + + + +void FetDriver::ADC_Callback(uint16_t channel, uint16_t value) +{ + + //ptrInstance->begin(); + if (ptrInstance==NULL) + { + return; + } + ptrInstance->ctrl_update(channel,value); + +} + +void FetDriver::ctrl_update(uint16_t channel, uint16_t value) +{ + int32_t x,error; + + if (channel == g_APinDescription[ISENSE_FET_A].ulADCChannelNumber) + { + static int32_t iterm; + + x=value-coilA_Zero; + error=coilA_SetPoint-x; + coilA_error=x; + iterm+=error; + + x=error*15;//+iterm/10; + x=x/1024; + coilA_value+=x; + +// if (error>0) +// coilA_value++; +// else +// coilA_value--; +// +// coilA_value+= iterm/1024; + coilA_PWM(coilA_value); +// if (error>0) +// { +// coilA(COIL_FORWARD); +// }else +// { +// coilA(COIL_BRAKE); +// } + + } + + if (channel == g_APinDescription[ISENSE_FET_B].ulADCChannelNumber) + { + static int32_t itermB; + x=value-coilB_Zero; + error=coilB_SetPoint-x; + coilB_error=error; + + + x=error*15+itermB/10; + x=x/1024; + coilB_value+=x; + + //coilB_PWM(coilB_value); +// if (error>0) +// { +// coilB(COIL_FORWARD); +// }else +// { +// coilB(COIL_BRAKE); +// } + + } + return; + + //LOG("channel is %d %d", channel,value); + if (channel == g_APinDescription[ISENSE_FET_B].ulADCChannelNumber) + { + static int32_t ib=0; + static int32_t meanb=0; + int32_t error,u,de; + static int32_t itermb=0;; + static int32_t lastErrorb=0; + + adc=value; + x=value-coilB_Zero; + if (coilB_Zero==-1) + { + if(ib0) + // u=1; + // else + // u=-1; + + de=error-lastErrorb; + lastErrorb=error; + + if (ABS(error)<50) + { + itermb=itermb+1*error; + }else + { + itermb=0; + } + u=error*320 + itermb +100*de; + u=u/16382; + if (u>10) u=10; + if (u<-10) u=-10; + + coilB_value+=u;; + //LOG("coil value %d, %d",coilB_value,u); + coilB_value=MIN(coilB_value,(int32_t)(F_CPU/FET_DRIVER_FREQ)); + coilB_value=MAX(coilB_value,(int32_t)(-(F_CPU/FET_DRIVER_FREQ))); + + coilB_PWM(coilB_value); + + return; + } + + if (channel == g_APinDescription[ISENSE_FET_A].ulADCChannelNumber) + { + static int32_t i=0; + static int32_t mean=0; + int32_t error,u,de; + static int32_t iterm=0;; + static int32_t lastError=0; + + + x=value-coilA_Zero; + if (coilA_Zero==-1) + { + if(i10) u=10; + if (u<-10) u=-10; + + coilA_value+=u; + //LOG("coil value %d, %d",coilB_value,u); + coilA_value=MIN(coilA_value,(int32_t)(F_CPU/FET_DRIVER_FREQ)); + coilA_value=MAX(coilA_value,(int32_t)(-(F_CPU/FET_DRIVER_FREQ))); + + coilA_PWM(coilA_value); + return; + } + +} + + +void FetDriver::measureCoilB_zero(void) +{ + coilB_Zero=GetMeanAdc(ISENSE_FET_B,FET_DRIVER_NUM_ZERO_AVG); + LOG("Coil B Zero is %d",coilB_Zero); + return; +} + +void FetDriver::measureCoilA_zero(void) +{ + coilA_Zero=GetMeanAdc(ISENSE_FET_A,FET_DRIVER_NUM_ZERO_AVG); + LOG("Coil A Zero is %d",coilA_Zero); + return; +} + + +void FetDriver::CalTableA(int32_t maxMA) +{ + + int16_t table2[512]={0}; + int32_t pwm=0; + int32_t mA=0; + int i; + + + while (mA>-maxMA) + { + int32_t adc; + //LOG("Running %d",pwm); + adc=GetMeanAdc(ISENSE_FET_A,10)-coilA_Zero; + //LOG("ADC is %d",adc); + mA=FET_ADC_TO_MA(adc); + //LOG("mA is %d, ADC %d",mA,ADC); + pwm=pwm-1; + + if (coilA_PWM(pwm)==1) + { + ERROR("CoilA PWM maxed"); + break; + } + //delay(5); + } + + //LOG("First PWM is %d %d",pwm, mA); + PWM_Table_A[0]=pwm; + table2[0]=mA; + i=1; + while (i<512) + { + int32_t adc; + adc=GetMeanAdc(ISENSE_FET_A,10)-coilA_Zero; + mA=FET_ADC_TO_MA(adc); + + //LOG("PWM %d, %d %d",i,mA,pwm); + if (mA>((i-255)*maxMA/256)) + { + PWM_Table_A[i]=pwm; + table2[i]=mA; + i++; + }else + { + pwm=pwm+1; + coilA_PWM(pwm); + //delay(5); + } + } + coilA_PWM(0); + + Serial.print("\n\r TABLE A \n\r");; + for (i=0; i<512; i++) + { + Serial.print(PWM_Table_A[i]); + Serial.print(","); + } + Serial.print("\n\r"); + + Serial.print("\n\r"); + for (i=0; i<512; i++) + { + Serial.print(table2[i]); + Serial.print(","); + } + Serial.print("\n\r"); +} + +void FetDriver::CalTableB(int32_t maxMA) +{ + + int16_t table2[512]={0}; + int32_t pwm=0; + int32_t mA=0; + int i; + + while (mA>-maxMA) + { + int32_t adc; + adc=GetMeanAdc(ISENSE_FET_B,10)-coilB_Zero; + mA=FET_ADC_TO_MA(adc); + pwm=pwm-1; + coilB_PWM(pwm); + //delay(5); + } + + //LOG("First PWM is %d %d",pwm, mA); + PWM_Table_B[0]=pwm; + table2[0]=mA; + i=1; + while (i<512) + { + int32_t adc; + adc=GetMeanAdc(ISENSE_FET_B,10)-coilB_Zero; + mA=FET_ADC_TO_MA(adc); + + //LOG("PWM %d, %d %d",i,mA,pwm); + if (mA>((i-255)*maxMA/256)) + { + PWM_Table_B[i]=pwm; + table2[i]=mA; + i++; + }else + { + pwm=pwm+1; + coilB_PWM(pwm); + //delay(5); + } + } + + coilB_PWM(0); + Serial.print("\n\r TABLE B \n\r"); + for (i=0; i<512; i++) + { + Serial.print(PWM_Table_B[i]); + Serial.print(","); + } + Serial.print("\n\r"); + + Serial.print("\n\r"); + for (i=0; i<512; i++) + { + Serial.print(table2[i]); + Serial.print(","); + } + Serial.print("\n\r"); +} + + +void FetDriver::begin() +{ + int16_t i; + uint32_t t0; + int32_t i0=0; + uint32_t zero,x,k; + int32_t max_mA; + + + ptrInstance=(FetDriver *)this; + //enable 1V reference + SYSCTRL->VREF.reg |= SYSCTRL_VREF_BGOUTEN; + ADCRead(ISENSE_FET_A); //setup the adc with fast timing + //nt32_t min,max,avg; + //Setup the FET inputs + GPIO_OUTPUT(PIN_FET_IN1); + GPIO_OUTPUT(PIN_FET_IN2); + GPIO_OUTPUT(PIN_FET_IN3); + GPIO_OUTPUT(PIN_FET_IN4); + GPIO_OUTPUT(PIN_FET_ENABLE); + GPIO_HIGH(PIN_FET_ENABLE); + + //setup the Pin peripheral setting correct + pinPeripheral(PIN_FET_IN2, PIO_TIMER_ALT); //TCC0 WO[7] + pinPeripheral(PIN_FET_IN1, PIO_TIMER_ALT); + SET_PIN_PERHERIAL(PIN_FET_IN4, PIO_TIMER_ALT); //TCC0 WO[7] + SET_PIN_PERHERIAL(PIN_FET_IN3, PIO_TIMER_ALT); + + pinPeripheral(ISENSE_FET_A, PIO_ANALOG); //AIN[0] + pinPeripheral(ISENSE_FET_B, PIO_ANALOG); //AIN[2] + + enableTCC0(); + coilB_PWM(0); + coilA_PWM(0); + delay(100); + measureCoilA_zero(); + measureCoilB_zero(); + + +// ADCStart(ISENSE_FET_A); + + + //return; +// while(1) +// { +// LOG("tick %d %d", TCC0->CC[1].reg,TCC0->CC[0].reg); +// LOG("%d %d",coilA_error,coilB_error); +// } + +// uint16_t data[1000]; +// ADCRead(ISENSE_FET_A); +// +// t0=micros(); +// GPIO_LOW(PIN_FET_IN2); +// GPIO_GPIO_OUTPUT(PIN_FET_IN2); +// GPIO_HIGH(PIN_FET_IN1); +// GPIO_GPIO_OUTPUT(PIN_FET_IN1); +// +// for (i=0; i<1000; i++) +// { +// data[i]=fastADCRead(ISENSE_FET_A); +// } +// coilA_PWM(0); +// +// t0=micros()-t0; +// +// Serial.print("\n\r Step response \n\r"); +// Serial.print(t0); +// +// Serial.print("\n\r Step response \n\r"); +// for (i=0; i<1000; i++) +// { +// Serial.print(data[i]); +// Serial.print(","); +// } +// Serial.print("\n\r"); +// +// while(1) +// { +// +// } + max_mA=NVM->motorParams.currentMa; + WARNING("Maximum current is %d",max_mA); + + + if (NVM->motorParams.parametersVaild && max_mA!=0) + { + CalTableA(max_mA); + CalTableB(max_mA); + + }else + { + WARNING("NVM is not correct default to 1500mA"); + max_mA=1500; + WARNING("calibrating phase A %dmA",max_mA); + CalTableA(max_mA); + WARNING("calibrating phase B %dmA",max_mA); + CalTableB(max_mA); + + } + return; + + //coilA_PWM(100); + + x=0; + while(1) + { + //LOG("Trying to move motor %d",x); + delay(1); + move(x, 1000); + x=x+256; + + } + + + return; // all done + + // //set DAC to mid level + // syncDAC(); + // DAC->DATA.reg = 0x2FF; // DAC on 10 bits. + // syncDAC(); + // DAC->CTRLA.bit.ENABLE = 0x01; // Enable DAC + // syncDAC(); + + // WARNING("Running ADC ISR test"); + // ADCRead(3); + + //LOG("coil value %d %d",coilB_value,coilB_Zero); + i=47; + x=0; + while(1) + { + int32_t adc,value; + int32_t mA; + + if (0) + { + + coilB_PWM(i); + delayMicroseconds(1000); + //LOG("%d",i); + //if (i==47 ) delay(50); + + if (x==0) + { + i=i+1; + if (i>200) + { + x=1; + //i=47; + + } + } + + if (x == 1) + { + i=i-1; + if (i<47) + { + x=2; + i=-47; + } + + } + + if (x == 2) + { + i=i-1; + if (i<-200) + { + x=3; + } + } + + if (x == 3) + { + i=i+1; + if (i>-47) + { + x=0; + i=47; + } + } + }else + { + + adc=ADCRead(ISENSE_FET_A); + value=adc-coilA_Zero; + + mA=(value*2206)/1000; + + + + // + //delay(500); + //NVIC_DisableIRQ(ADC_IRQn); + + LOG("coil A %d %d, %d ",coilA_Zero, value, mA ); + + } + // NVIC_DisableIRQ(ADC_IRQn); + // + // NVIC_EnableIRQ(ADC_IRQn); + } + + x=0; + for (k=0; k<128; k++) + { + x=x+ADCRead(8); + } + zero=x/32; + + //setupDAC(); + //setDAC(5,5); + enableTCC0(); + //setupComparators(); + + + ERROR("Enable PWM"); + pinPeripheral(PIN_FET_IN4, PIO_TIMER_ALT); //TCC0 WO[7] + + // + // for (i=40; i<55; i++) + // { + // coilB_PWM(i); + // delay(200); + // ADCRead(8,16); + // LOG("COMP is 0x%04X ", AC->STATUSA.reg); + // LOG("%d ADC is %d ",i, ADCRead(8,16)); + // YELLOW_LED(0); + // } + + //ADCRead(8,16); + //AC->INTENCLR.bit.COMP1=1; + //coilA_Value=0; + + coilB_PWM(0); + + i=47; + coilB_PWM(i); + while(1) + { + int32_t x=0,k; + coilB_PWM(i); + delay(3000); + for (k=0; k<128; k++) + { + x=x+ADCRead(8); + } + x=x/32; + LOG("%d %d %d",i,x-zero,(x*3300)/(4096*4)); + LOG("%d",((x-zero)*5517)/10000); + + i=i+20; + if (i>140) + { + i=47; + } + + } + /* AC->INTENSET.bit.COMP1=1; + while(1) + { + AC->INTENCLR.bit.COMP1=1; + YELLOW_LED(0); + AC->INTENSET.bit.COMP1=1; + if ((millis()-t0)>10000) + { + int j; + min=0xFFFFFF; + max=(int16_t)ADCRead(8,16); + avg=0; + j=0; + t0=micros(); + while( (micros()-t0)<1000) + { + int16_t valueRead; + + valueRead = ADCRead(8,16); + + if (valueReadmax) + { + max=valueRead; + } + avg+=valueRead; + j++; + } + + + int32_t ma,x,duty; + duty=i-45; + duty=(1000*duty)/(F_CPU/FET_DRIVER_FREQ); + + LOG("min %d max %d, avg %d j %d, %d", min, max, (avg*10)/j, j,(avg*10)/j*(1000-duty)/1000); + + x=(avg*10)/j*(1000-duty)/1000; + x=(x*600)/1000+200; + + LOG("mA %d\n\r",x); + + if (i<150) + { + i=100; + }else + { + i=45; + } + LOG("COMP is 0x%04X ", AC->STATUSA.reg); + LOG("%d ADC is %d %d",i, ADCRead(8,16),coilA_Value); + t0=millis(); + AC->INTENCLR.bit.COMP1=1; + coilA_Value=0; + coilB_PWM(i); + AC->INTENSET.bit.COMP1=1; + } + } + */ + return; + + //setup the PWM for current on the A4954, set for low current + digitalWrite(PIN_A4954_VREF12,LOW); + digitalWrite(PIN_A4954_VREF34,LOW); + pinMode(PIN_A4954_VREF34, OUTPUT); + pinMode(PIN_A4954_VREF12, OUTPUT); + + enabled=true; + lastStepMicros=0; + forwardRotation=true; + + enableTCC0(); + setupDAC(); + // + // WARNING("Setting DAC for 500mA output"); + // setDAC((int32_t)((int64_t)1000*(DAC_MAX))/3300,(int32_t)((int64_t)1000*(DAC_MAX))/3300); + // bridge1(0); + // bridge2(0); + // while(1) + // { + // + // } + return; +} + + + + + + + + +int32_t FetDriver::getCoilB_mA(void) +{ + int32_t adc,ret; + //fastADCRead(ISENSE_FET_B); + adc=(int32_t)fastADCRead(ISENSE_FET_B); + ret=FET_ADC_TO_MA(adc-coilB_Zero); + //LOG("coilb %d %d",adc,ret); + return ret; +} +int32_t FetDriver::getCoilA_mA(void) +{ + int32_t adc,ret; + //fastADCRead(ISENSE_FET_A); + adc=(int32_t)fastADCRead(ISENSE_FET_A); + ret=FET_ADC_TO_MA(adc-coilA_Zero); + //LOG("coila %d %d",adc,ret); + return ret; +} + + +//this is precise move and modulo of A4954_NUM_MICROSTEPS is a full step. +// stepAngle is in A4954_NUM_MICROSTEPS units.. +// The A4954 has no idea where the motor is, so the calling function has to +// to tell the A4954 what phase to drive motor coils. +// A4954_NUM_MICROSTEPS is 256 by default so stepAngle of 1024 is 360 degrees +// Note you can only move up to +/-A4954_NUM_MICROSTEPS from where you +// currently are. +int32_t FetDriver::move(int32_t stepAngle, uint32_t mA) +{ + uint16_t angle; + int32_t cos,sin; + int32_t dacSin,dacCos; + int32_t dacSin_mA,dacCos_mA; + int32_t maxMa; + static int32_t last_dacSin_mA=0,last_dacCos_mA=0;; + if (enabled == false) + { + WARNING("FET Driver disabled"); + + //turn the current off to FETs + coilA_PWM(0); + coilB_PWM(0); + + //float the FET outputs by disabling FET driver. + GPIO_LOW(PIN_FET_ENABLE); + return stepAngle; + } + GPIO_HIGH(PIN_FET_ENABLE); + + + maxMa=NVM->motorParams.currentMa; + if (maxMa==0) + { + maxMa=2200; + } + + //WARNING("move %d %d",stepAngle,mA); + //handle roll overs, could do with modulo operator + //stepAngle=stepAngle%SINE_STEPS; + // while (stepAngle<0) + // { + // stepAngle=stepAngle+SINE_STEPS; + // } + // while (stepAngle>=SINE_STEPS) + // { + // stepAngle=stepAngle-SINE_STEPS; + // } + + //figure out our sine Angle + // note our SINE_STEPS is 4x of microsteps for a reason + //angle=(stepAngle+(SINE_STEPS/8)) % SINE_STEPS; + angle=(stepAngle) % SINE_STEPS; + //calculate the sine and cosine of our angle + sin=sine(angle); + cos=cosine(angle); + + //if we are reverse swap the sign of one of the angels + if (false == forwardRotation) + { + cos=-cos; + } + + //LOG("sin/cos %d %d %d", sin,cos,angle); + //scale sine result by current(mA) + dacSin_mA=((int32_t)mA*(int32_t)(sin))/SINE_MAX; + + //scale cosine result by current(mA) + dacCos_mA=((int32_t)mA*(int32_t)(cos))/SINE_MAX; + + coilA_SetPoint=FET_MA_TO_ADC(dacSin_mA); + coilB_SetPoint=FET_MA_TO_ADC(dacCos_mA); + //LOG("sin/cos %d %d", dacSin,dacCos); + + //convert value into 12bit DAC scaled to 3300mA max + dacSin=(int32_t)((int64_t)dacSin_mA*(255))/maxMa; + + //convert value into 12bit DAC scaled to 3300mA max + dacCos=(int32_t)((int64_t)dacCos_mA*(255))/maxMa; + + //LOG("sin/cos %d %d", dacSin,dacCos); + //limit the table index to +/-255 + dacCos=MIN(dacCos,(int32_t)255); + dacCos=MAX(dacCos,(int32_t)-255); + dacSin=MIN(dacSin,(int32_t)255); + dacSin=MAX(dacSin,(int32_t)-255); + + + if ((dacSin_mA-last_dacSin_mA)>200) + { + GPIO_LOW(PIN_FET_IN2); + PIN_GPIO_OUTPUT(PIN_FET_IN2); + GPIO_HIGH(PIN_FET_IN1); + PIN_GPIO_OUTPUT(PIN_FET_IN1); + }else if ((dacSin_mA-last_dacSin_mA)<-200) + { + GPIO_HIGH(PIN_FET_IN2); + PIN_GPIO_OUTPUT(PIN_FET_IN2); + GPIO_LOW(PIN_FET_IN1); + PIN_GPIO_OUTPUT(PIN_FET_IN1); + } + + if ((dacCos_mA-last_dacCos_mA)>200) + { + GPIO_LOW(PIN_FET_IN4); + PIN_GPIO_OUTPUT(PIN_FET_IN4); + GPIO_HIGH(PIN_FET_IN3); + PIN_GPIO_OUTPUT(PIN_FET_IN3); + }else if ((dacCos_mA-last_dacCos_mA)<-200) + { + GPIO_HIGH(PIN_FET_IN4); + PIN_GPIO_OUTPUT(PIN_FET_IN4); + GPIO_LOW(PIN_FET_IN3); + PIN_GPIO_OUTPUT(PIN_FET_IN3); + } + delayMicroseconds(20); + last_dacSin_mA=dacSin_mA; + last_dacCos_mA=dacCos_mA; + +// YELLOW_LED(1); +// uint32_t t0=micros(); +// int done=0; +// int32_t a,b; +// a=FET_MA_TO_ADC(dacSin_mA); +// b=FET_MA_TO_ADC(dacCos_mA); +// while ((micros()-t0)<20 && done!=0x03) +// { +// if ( (fastADCRead(ISENSE_FET_A)-a)FET_MA_TO_ADC(200)) +// { +// GPIO_HIGH(PIN_FET_IN2); +// PIN_GPIO_OUTPUT(PIN_FET_IN2); +// GPIO_LOW(PIN_FET_IN1); +// PIN_GPIO_OUTPUT(PIN_FET_IN1); +// done |=0x01; +// } +// if ((fastADCRead(ISENSE_FET_B)-b)FET_MA_TO_ADC(200)) +// { +// GPIO_HIGH(PIN_FET_IN4); +// PIN_GPIO_OUTPUT(PIN_FET_IN4); +// GPIO_LOW(PIN_FET_IN3); +// PIN_GPIO_OUTPUT(PIN_FET_IN3); +// done |=0x02; +// } +// +// } +// +// YELLOW_LED(0); + + + //LOG("sin/cos %d %d", dacSin,dacCos); + //loop up the current from table and set the PWM + coilA_PWM(PWM_Table_A[dacSin+255]); + coilB_PWM(PWM_Table_B[dacCos+255]); + + lastStepMicros=micros(); + return stepAngle; +} +#pragma GCC pop_options //fast optimization + +#endif //NEMA_23_10A_HW + +#pragma GCC pop_options diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.h b/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.h new file mode 100644 index 0000000..a056897 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.h @@ -0,0 +1,124 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#ifndef FET_DRIVER_H_ +#define FET_DRIVER_H_ + + + +#include +#include "board.h" +#include "angle.h" +#include "sine.h" + +#ifdef NEMA_23_10A_HW +#define FET_DRIVER_NUM_MICROSTEPS (SINE_STEPS/4) //number of steps to use for microstepping, default is 256 +#define FET_DRIVER_NUM_ZERO_AVG (100) + + +#define FET_ADC_TO_MA(x) (((x)*2537)/1000) +#define FET_MA_TO_ADC(x) (((x)*1000)/2537) +//prvent someone for making a mistake with the code +#if ((FET_DRIVER_NUM_MICROSTEPS*4) != SINE_STEPS) +#error "SINE_STEPS must be 4x of Micro steps for the move function" +#endif + +/* + * When it comes to the stepper driver if we use angles + * we will always have a rounding error. For example + * a 0-65536(360) angle for 1.8 degree step is 327.68 so + * if you increment 200 of these as 327 you have a 13.6 error + * after one rotation. + * If you use floating point the effect is the same but takes longer. + * + * The only error-less accumulation system is to use native units, ie full + * steps and microsteps. + * + */ + +class FetDriver +{ + static FetDriver *ptrInstance; +private: + uint32_t lastStepMicros; // time in microseconds that last step happened + + int32_t PWM_Table_B[512]; + int32_t PWM_Table_A[512]; + + bool forwardRotation=true; + volatile bool enabled=true; + + volatile int32_t adc; + + + volatile int32_t coilB_value=0; + volatile int32_t coilB_Zero=-1; + volatile int32_t coilB_SetPoint=100; + volatile int32_t coilB_error=0; + + volatile int32_t coilA_value=0; + volatile int32_t coilA_Zero=-1; + volatile int32_t coilA_SetPoint=200; + volatile int32_t coilA_error=0; + void ctrl_update(uint16_t channel, uint16_t value); + void measureCoilB_zero(void); + void measureCoilA_zero(void); + void CalTableB(int32_t maxMA); + void CalTableA(int32_t maxMA); + int coilA_PWM(int32_t value); + void coilB_PWM(int32_t value); + int32_t getCoilB_mA(void); + int32_t getCoilA_mA(void); +public: + + static void ADC_Callback(uint16_t channel, uint16_t value); + void begin(void); + + //moves motor where the modulo of A4954_NUM_MICROSTEPS is a full step. + int32_t move(int32_t stepAngle, uint32_t mA); + + uint32_t microsSinceStep(void) {return micros()-lastStepMicros;}; + void setRotationDirection(bool forward) {forwardRotation=forward;}; + + void enable(bool enable) {enabled=enable;}; + void limitCurrent(uint8_t x) {return;}; +}; + + +#endif //#ifdef NEMA_23_10A_HW +#endif /* FET_DRIVER_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.cpp new file mode 100644 index 0000000..8ff7f42 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.cpp @@ -0,0 +1,193 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "board.h" +#include "ftoa.h" +/******************************************************************* + * FUNCTION: ftoa + * AUTHOR = TRAMPAS STERN + * FILE = strio.c + * DATE = 2/6/2003 4:27:14 PM + * + * PARAMETERS: long,*str, int count + * + * DESCRIPTION: Convets an float to string + * format 'f', 'E', or 'e' + * + * + * RETURNS: + * + * NOTE this code was found on the web and modified to actually work + *******************************************************************/ + int ftoa (float x, char *str, char prec, char format) + { + + int ie, i, k, ndig, fstyle; + double y; + char *start; + + start=str; + + //based on percission set number digits + ndig=prec+1; + if (prec<0) + ndig=7; + if (prec>22) + ndig=23; + + fstyle = 0; //exponent 'e' + if (format == 'f' || format == 'F') + fstyle = 1; //normal 'f' + if (format=='g' || format=='G') + fstyle=2; + + ie = 0; + /* if x negative, write minus and reverse */ + if ( x < 0) + { + *str++ = '-'; + x = -x; + } + + //if (x<0.0) then increment by 10 till betwen 1.0 and 10.0 + if (x!=0.0) + { + while (x < 1.0) + { + x =x* 10.0; + ie--; + } + } + + //if x>10 then let's shift it down + while (x >= 10.0) + { + x = x*(1.0/10.0); + ie++; + } + + if (ABS(ie)>MAX_MANTISA) + { + if (fstyle==1) + { + fstyle=0; + format='e'; + //ie=2; + } + } + + + /* in f format, number of digits is related to size */ + if (fstyle) + ndig =ndig + ie; + + if(prec==0 && ie>ndig && fstyle) + { + ndig=ie; + } + + /* round. x is between 1 and 10 and ndig will be printed to + right of decimal point so rounding is ... */ + y=1; + for (i = 1; i < ndig; i++) //find lest significant digit + y = y *(1.0/10.0); //multiply by 1/10 is faster than divides + + x = x+ y *(1.0/2.0); //add rounding + + /* repair rounding disasters */ + if (x >= 10.0) + { + x = 1.0; + ie++; + ndig++; + } + + //check and see if the number is less than 1.0 + if (fstyle && ie<0) + { + *str++ = '0'; + if (prec!=0) + *str++ = '.'; + if (ndig < 0) + ie = ie-ndig; /* limit zeros if underflow */ + for (i = -1; i > ie; i--) + *str++ = '0'; + } + + //for each digit + for (i=0; i < ndig; i++) + { + float b; + k = x; //k = most significant digit + *str++ = k + '0'; //output the char representation + if (((!fstyle && i==0) || (fstyle && i==ie)) && prec!=0) + *str++ = '.'; //output a decimal point + b=(float)k; + //multiply by 10 before subtraction to remove + //errors from limited number of bits in float. + b=b*10.0; + x=x*10.0; + x =x - b; //subtract k from x + //b=x+b; + //x =x* 10.0; //get next digit + } + + /* now, in estyle, put out exponent if not zero */ + if (!fstyle && ie != 0) + { + *str++ = format; + if (ie < 0) //if number has negative exponent + { + ie = -ie; + *str++ = '-'; + } + + //now we need to convert the exponent to string + for (k=1000; k>ie; k=k/10); //find the decade of exponent + + for (; k > 0; k=k/10) + { + char t; + t=DIV(ie,k); + *str++ = t + '0'; + ie = ie -(t*k); + } + + } + *str++ = '\0'; + return (str-start); //return string length + } diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.h b/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.h new file mode 100644 index 0000000..55000ff --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.h @@ -0,0 +1,48 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#ifndef FTOA_H_ +#define FTOA_H_ + +#define MAX_MANTISA (1000) + +int ftoa (float x, char *str, char prec, char format); + + + +#endif /* FTOA_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/gfxfont.h b/firmware_smartstepper_trikarus/stepper_nano_zero/gfxfont.h new file mode 100644 index 0000000..07381ed --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/gfxfont.h @@ -0,0 +1,24 @@ +// Font structures for newer Adafruit_GFX (1.1 and later). +// Example fonts are included in 'Fonts' directory. +// To use a font in your Arduino sketch, #include the corresponding .h +// file and pass address of GFXfont struct to setFont(). Pass NULL to +// revert to 'classic' fixed-space bitmap font. + +#ifndef _GFXFONT_H_ +#define _GFXFONT_H_ + +typedef struct { // Data stored PER GLYPH + uint16_t bitmapOffset; // Pointer into GFXfont->bitmap + uint8_t width, height; // Bitmap dimensions in pixels + uint8_t xAdvance; // Distance to advance cursor (x axis) + int8_t xOffset, yOffset; // Dist from cursor pos to UL corner +} GFXglyph; + +typedef struct { // Data stored for FONT AS A WHOLE: + uint8_t *bitmap; // Glyph bitmaps, concatenated + GFXglyph *glyph; // Glyph array + uint8_t first, last; // ASCII extents + uint8_t yAdvance; // Newline distance (y axis) +} GFXfont; + +#endif // _GFXFONT_H_ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/glcdfont.c b/firmware_smartstepper_trikarus/stepper_nano_zero/glcdfont.c new file mode 100644 index 0000000..6f88bd2 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/glcdfont.c @@ -0,0 +1,276 @@ +// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0. +// See gfxfont.h for newer custom bitmap font info. + +#ifndef FONT5X7_H +#define FONT5X7_H + +#ifdef __AVR__ + #include + #include +#elif defined(ESP8266) + #include +#else + #define PROGMEM +#endif + +// Standard ASCII 5x7 font + +static const unsigned char font[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, + 0x10, 0x20, 0x7E, 0x20, 0x10, + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP +}; +#endif // FONT5X7_H diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.cpp new file mode 100644 index 0000000..32d5465 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.cpp @@ -0,0 +1,145 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "nonvolatile.h" +#include "Flash.h" //thanks to Kent Larsen for pointing out the lower case error +#include + + + + +//we use this so we can hard code calibration table +// be sure to set the last word as status flag +// this save time calibrating each time we do a code build +#ifdef NZS_FAST_CAL +__attribute__((__aligned__(FLASH_ROW_SIZE))) const uint16_t NVM_flash[16767]={ //allocates 33280 bytes +#else +__attribute__((__aligned__(FLASH_ROW_SIZE))) const uint16_t NVM_flash[256]={ //allocates 512 bytes +#endif +25758,26078,26399,26720,27043,27372,27698,28024,28353,28688,29017,29345,29671,30009,30340,30663,30997,31335,31664,31994,32325,32666,32997,33324,33661,33997,34330,34657,34986,35324,35653,35981,36303,36637,36962,37282,37605,37938,38260,38581,38901,39232,39554,39877,40198,40528,40849,41178,41500,41835,42163,42485,42815,43149,43475,43804,44139,44476,44801,45136,45460,45804,46130,46460,46790,47119,47449,47777,48103,48442,48772,49099,49424,49759,50087,50410,50735,51067,51394,51716,52045,52379,52703,53024,53348,53680,54002,54326,54648,54987,55309,55629,55958,56292,56612,56936,57262,57594,57917,58246,58569,58902,59225,59552,59873,60206,60534,60862,61192,61531,61864,62194,62529,62873,63210,63544,63878,64222,64562,64899,65241,45,384,719,1058,1398,1733,2058,2390,2732,3060,3394,3720,4056,4386,4710,5036,5366,5693,6016,6340,6665,6989,7308,7622,7952,8263,8586,8903,9232,9551,9874,10200,10534,10859,11185,11513,11852,12184,12514,12848,13185,13511,13841,14170,14504,14830,15156,15490,15827,16153,16481,16808,17143,17474,17801,18121,18458,18783,19111,19433,19765,20084,20405,20721,21045,21360,21673,21984,22305,22614,22922,23231,23551,23861,24173,24482,24808,25118,25435, + + 0xFFFF +}; + + + +static_assert (sizeof(nvm_t)CalibrationTable,ptrData,size); + return true; +} + +bool nvmWrite_sPID(float Kp, float Ki, float Kd) +{ + PIDparams_t pid; + + pid.Kp=Kp; + pid.Ki=Ki; + pid.Kd=Kd; + pid.parametersVaild=true; + + flashWrite((void *)&NVM->sPID,&pid,sizeof(pid)); + return true; +} + +bool nvmWrite_vPID(float Kp, float Ki, float Kd) +{ + PIDparams_t pid; + + pid.Kp=Kp; + pid.Ki=Ki; + pid.Kd=Kd; + pid.parametersVaild=true; + + flashWrite((void *)&NVM->vPID,&pid,sizeof(pid)); + return true; +} + +bool nvmWrite_pPID(float Kp, float Ki, float Kd) +{ + PIDparams_t pid; + + pid.Kp=Kp; + pid.Ki=Ki; + pid.Kd=Kd; + pid.parametersVaild=true; + + flashWrite((void *)&NVM->pPID,&pid,sizeof(pid)); + return true; +} + +bool nvmWriteSystemParms(SystemParams_t &systemParams) +{ + systemParams.parametersVaild=true; + + flashWrite((void *)&NVM->SystemParams,&systemParams,sizeof(systemParams)); + return true; +} + +bool nvmWriteMotorParms(MotorParams_t &motorParams) +{ + motorParams.parametersVaild=true; + + flashWrite((void *)&NVM->motorParams,&motorParams,sizeof(motorParams)); + return true; +} + +bool nvmErase(void) +{ + bool data=false; + uint16_t cs=0; + + flashWrite((void *)&NVM->CalibrationTable.status,&data,sizeof(data)); + flashWrite((void *)&NVM->sPID.parametersVaild ,&data,sizeof(data)); + flashWrite((void *)&NVM->vPID.parametersVaild ,&data,sizeof(data)); + flashWrite((void *)&NVM->pPID.parametersVaild ,&data,sizeof(data)); + flashWrite((void *)&NVM->motorParams.parametersVaild ,&data,sizeof(data)); + flashWrite((void *)&NVM->SystemParams.parametersVaild ,&data,sizeof(data)); +#ifdef NZS_FAST_CAL + flashWrite((void *)&NVM->FastCal.checkSum,&cs,sizeof(cs)); +#endif +} + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.h b/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.h new file mode 100644 index 0000000..3e29c03 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.h @@ -0,0 +1,108 @@ +/********************************************************************** + Copyright (C) 2018 MisfitTech LLC, All rights reserved. + + MisfitTech uses a dual license model that allows the software to be used under + a standard GPL open source license, or a commercial license. The standard GPL + license requires that all software statically linked with MisfitTec Code is + also distributed under the same GPL V2 license terms. Details of both license + options follow: + + - Open source licensing - + MisfitTech is a free download and may be used, modified, evaluated and + distributed without charge provided the user adheres to version two of the GNU + General Public License (GPL) and does not remove the copyright notice or this + text. The GPL V2 text is available on the gnu.org web site + + - Commercial licensing - + Businesses and individuals that for commercial or other reasons cannot comply + with the terms of the GPL V2 license must obtain a low cost commercial license + before incorporating MisfitTech code into proprietary software for distribution in + any form. Commercial licenses can be purchased from www.misfittech.net + and do not require any source files to be changed. + + + This code is distributed in the hope that it will be useful. You cannot + use MisfitTech's code unless you agree that you use the software 'as is'. + MisfitTech's code is provided WITHOUT ANY WARRANTY; without even the implied + warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. MisfitTech LLC disclaims all conditions and terms, be they + implied, expressed, or statutory. + + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __NONVOLATILE__H__ +#define __NONVOLATILE__H__ + +#include "calibration.h" +#include "board.h" + + +typedef struct { + float Kp; + float Ki; + float Kd; + bool parametersVaild; +} PIDparams_t; + +typedef struct { + int32_t currentMa; //maximum current for the motor + int32_t currentHoldMa; //hold current for the motor + int32_t homeMa; //maximum current when error homing + int32_t homeHoldMa; //hold current when error homing + bool motorWiring; //forward wiring of motor or reverse + int32_t fullStepsPerRotation; //how many full steps per rotation is the motor + bool parametersVaild; +} MotorParams_t; + +typedef struct { + int32_t microsteps; //number of microsteps on the dir/step pin interface from host + RotationDir_t dirPinRotation; //is the direction pin high for clockwise or counterClockWise + int32_t errorLimit; //error limit before error pin asserts 65536==360degrees + ErrorPinMode_t errorPinMode; //is error pin used for enable, error, or bidirectional + feedbackCtrl_t controllerMode; //feedback mode for the controller + int32_t homePin; //if greater than zero this is the pin we use trigger home current settings + bool errorLogic; //if high and error will be high on output pin + int32_t homeAngleDelay; //the angle to delay before switching to lower homing current + bool parametersVaild; +} SystemParams_t; + +#ifdef NZS_FAST_CAL +typedef struct { + uint16_t angle[16384]; + uint16_t checkSum; +}FastCal_t; +#endif + +typedef struct { + FlashCalData_t CalibrationTable; + __attribute__((__aligned__(8))) PIDparams_t sPID; //simple PID parameters + __attribute__((__aligned__(8))) PIDparams_t pPID; //position PID parameters + __attribute__((__aligned__(8))) PIDparams_t vPID; //velocity PID parameters + __attribute__((__aligned__(8))) SystemParams_t SystemParams; + __attribute__((__aligned__(8))) MotorParams_t motorParams; +#ifdef NZS_FAST_CAL + __attribute__((__aligned__(8))) FastCal_t FastCal; +#endif +} nvm_t; + +#ifdef NZS_FAST_CAL +extern const uint16_t NVM_flash[16767]; +#else +extern const uint16_t NVM_flash[256]; +#endif +#define NVM ((const nvm_t *)NVM_flash) + +bool nvmWriteCalTable(void *ptrData, uint32_t size); +bool nvmWrite_sPID(float Kp, float Ki, float Kd); +bool nvmWrite_pPID(float Kp, float Ki, float Kd); +bool nvmWrite_vPID(float Kp, float Ki, float Kd); +bool nvmWriteSystemParms(SystemParams_t &systemParams); +bool nvmWriteMotorParms(MotorParams_t &motorParams); +bool nvmErase(void); + +#endif // __NONVOLATILE__H__ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.cpp new file mode 100644 index 0000000..cc2dbbd --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.cpp @@ -0,0 +1,902 @@ +/* + * nzs.cpp + * + * Created on: Dec 8, 2016 + * Author: trampas + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#include "nzs.h" +#include "commands.h" +#include "nonvolatile.h" +#include "angle.h" +#include "eeprom.h" +#include "steppin.h" +#include "wiring_private.h" + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + +eepromData_t PowerupEEPROM={0}; + + +volatile bool enableState=true; + +int32_t dataEnabled=0; + +StepperCtrl stepperCtrl; +LCD Lcd; + +int menuCalibrate(int argc, char *argv[]) +{ + stepperCtrl.calibrateEncoder(); +} + +int menuTestCal(int argc, char *argv[]) +{ + Angle error; + int32_t x,y; + char str[25]; + error=stepperCtrl.maxCalibrationError(); + + x=(36000*(int32_t)error)/ANGLE_STEPS; + LOG("Error %d %d", (int32_t)error, x); + y=x/100; + x=x-(y*100); + x=abs(x); + sprintf(str, "%d.%02d deg",y,x); +#ifndef DISABLE_LCD + Lcd.lcdShow("Cal Error", str,""); +#endif + + LOG("Calibration error %s",str); +#ifndef MECHADUINO_HARDWARE + while(digitalRead(PIN_SW3)==1) + { + //wait for button press + } + while(digitalRead(PIN_SW3)==0) + { + //wait for button release + } +#endif +} + +static options_t stepOptions[] { + {"200"}, + {"400"}, + {""}, +}; + +//returns the index of the stepOptions when called +// with no arguments. +int motorSteps(int argc, char *argv[]) +{ + if (argc==0) + { + int i; + i=NVM->motorParams.fullStepsPerRotation; + if (i==400) + { + return 1; + } + return 0; //default to 200 + } + if (argc>0) + { + int32_t i; + MotorParams_t params; + memcpy((void *)¶ms, (void *)&NVM->motorParams, sizeof(params)); + i=atol(argv[0]); + if (i!=params.fullStepsPerRotation) + { + params.fullStepsPerRotation=i; + nvmWriteMotorParms(params); + } + } + + return 0; +} + +static options_t currentOptions[] { + {"0"}, + {"100"}, + {"200"}, + {"300"}, + {"400"}, + {"500"}, + {"600"}, + {"700"}, + {"800"}, + {"900"}, + {"1000"}, + {"1100"}, + {"1200"}, + {"1300"}, + {"1400"}, + {"1500"}, + {"1600"}, + {"1700"}, + {"1800"}, + {"1900"}, + {"2000"}, + {"2100"}, + {"2200"}, + {"2300"}, + {"2400"}, + {"2500"}, + {"2600"}, + {"2700"}, + {"2800"}, + {"2900"}, + {"3000"}, + {"3100"}, + {"3200"}, + {"3300"}, + {""}, +}; + +int motorCurrent(int argc, char *argv[]) +{ + LOG("called motorCurrent %d",argc); + if (argc==1) + { + int i; + LOG("called %s",argv[0]); + i=atol(argv[0]); + i=i*100; + MotorParams_t params; + memcpy((void *)¶ms, (void *)&NVM->motorParams, sizeof(params)); + if (i!=params.currentMa) + { + params.currentMa=i; + nvmWriteMotorParms(params); + } + return i/100; + } + int i; + i=NVM->motorParams.currentMa/100; + LOG(" motorCurrent return %d",i); + return i; + +} + +int motorHoldCurrent(int argc, char *argv[]) +{ + if (argc==1) + { + int i; + i=atol(argv[0]); + i=i*100; + MotorParams_t params; + memcpy((void *)¶ms, (void *)&NVM->motorParams, sizeof(params)); + if (i!=params.currentHoldMa) + { + params.currentHoldMa=i; + nvmWriteMotorParms(params); + } + return i/100; + }else + { + int i; + i=NVM->motorParams.currentHoldMa/100; + return i; + } +} + +static options_t microstepOptions[] { + {"1"}, + {"2"}, + {"4"}, + {"8"}, + {"16"}, + {"32"}, + {"64"}, + {"128"}, + {"256"}, + {""} +}; + +int microsteps(int argc, char *argv[]) +{ + if (argc==1) + { + int i,steps; + i=atol(argv[0]); + SystemParams_t params; + memcpy((void *)¶ms, (void *)&NVM->SystemParams, sizeof(params)); + steps=0x01<SystemParams.microsteps; + for (j=0; j<9; j++) + { + + if ((0x01<SystemParams, sizeof(params)); + if (i!=params.controllerMode) + { + params.controllerMode=(feedbackCtrl_t)i; + nvmWriteSystemParms(params); + } + return i; + } + return NVM->SystemParams.controllerMode; +} + + + + +#ifndef PIN_ENABLE +static options_t errorPinOptions[] { + {"Enable"}, + {"!Enable"}, //error pin works like enable on step sticks + {"Error"}, + // {"BiDir"}, //12/12/2016 not implemented yet + {""} +}; + +int errorPin(int argc, char *argv[]) +{ + if (argc==1) + { + int i; + i=atol(argv[0]); + SystemParams_t params; + memcpy((void *)¶ms, (void *)&NVM->SystemParams, sizeof(params)); + if (i!=params.errorPinMode) + { + params.errorPinMode=(ErrorPinMode_t)i; + nvmWriteSystemParms(params); + } + return i; + } + return NVM->SystemParams.errorPinMode; +} +#else + + static options_t errorPinOptions[] { + {"Enable"}, + {"!Enable"}, //error pin works like enable on step sticks + // {"Error"}, + // {"BiDir"}, //12/12/2016 not implemented yet + {""} + }; + + int enablePin(int argc, char *argv[]) + { + if (argc==1) + { + int i; + i=atol(argv[0]); + SystemParams_t params; + memcpy((void *)¶ms, (void *)&NVM->SystemParams, sizeof(params)); + if (i!=params.errorPinMode) + { + params.errorPinMode=(ErrorPinMode_t)i; + nvmWriteSystemParms(params); + } + return i; + } + return NVM->SystemParams.errorPinMode; + } + +#endif + +static options_t dirPinOptions[] { + {"High CW"}, + {"High CCW"}, + {""} +}; + +int dirPin(int argc, char *argv[]) +{ + if (argc==1) + { + int i; + i=atol(argv[0]); + SystemParams_t params; + memcpy((void *)¶ms, (void *)&NVM->SystemParams, sizeof(params)); + if (i!=params.dirPinRotation) + { + params.dirPinRotation=(RotationDir_t)i; + nvmWriteSystemParms(params); + } + return i; + } + return NVM->SystemParams.dirPinRotation; +} + + +static menuItem_t MenuMain[] { + {"Calibrate", menuCalibrate,NULL}, + {"Test Cal", menuTestCal,NULL}, + // {"Mtr steps", motorSteps,stepOptions}, NOT GOOD for user to call this + {"Motor mA", motorCurrent,currentOptions}, + {"Hold mA", motorHoldCurrent,currentOptions}, + {"Microstep", microsteps,microstepOptions}, + // {"Ctlr Mode", controlLoop,controlLoopOptions}, //this may not be good for user to call +#ifndef PIN_ENABLE + {"Error Pin", errorPin,errorPinOptions}, +#else + {"EnablePin", enablePin,errorPinOptions}, +#endif + {"Dir Pin", dirPin,dirPinOptions}, + + + { "", NULL} +}; + +static menuItem_t MenuCal[] { + {"Calibrate", menuCalibrate,NULL}, + //{"Test Cal", menuTestCal,NULL}, + { "", NULL} +}; + + + + + + +//this function is called when error pin changes as enable signal +static void enableInput(void) +{ + static bool lastState=true; +#ifdef PIN_ENABLE + if (NVM->SystemParams.errorPinMode == ERROR_PIN_MODE_ENABLE) + { + static int enable; + //read our enable pin + enable = digitalRead(PIN_ENABLE); + if (enable != enableState) + { + WARNING("Enable now %d",enable); + } + enableState=enable; + //stepperCtrl.enable(enable); + } + if (NVM->SystemParams.errorPinMode == ERROR_PIN_MODE_ACTIVE_LOW_ENABLE) + { + static int enable; + //read our enable pin + enable = !digitalRead(PIN_ENABLE); + if (enable != enableState) + { + WARNING("Enable now %d",enable); + } + enableState=enable; + //stepperCtrl.enable(enable); + } +#else + if (NVM->SystemParams.errorPinMode == ERROR_PIN_MODE_ENABLE) + { + static int enable; + //read our enable pin + enable = digitalRead(PIN_ERROR); + enableState=enable; + //stepperCtrl.enable(enable); + } + if (NVM->SystemParams.errorPinMode == ERROR_PIN_MODE_ACTIVE_LOW_ENABLE) + { + static int enable; + //read our enable pin + enable = !digitalRead(PIN_ERROR); + enableState=enable; + //stepperCtrl.enable(enable); + } +#endif + +#ifdef USE_STEP_DIR_SERIAL + + static uint8_t pinCFG[2]; + static uint8_t pinMux[2]; + if (enableState == false && lastState==true) + { + // turn the step/dir to serial port + + //save pin config for restoring + pinCFG[0]=getPinCfg(PIN_STEP_INPUT); + pinCFG[1]=getPinCfg(PIN_DIR_INPUT); + pinMux[0]=getPinMux(PIN_STEP_INPUT); + pinMux[1]=getPinMux(PIN_DIR_INPUT); + + //lets see if the step pin has interrupt enabled + if (pinMux[0] == PORT_PMUX_PMUXE_A_Val) + { + EExt_Interrupts in = g_APinDescription[PIN_STEP_INPUT].ulExtInt; + EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << in); //disable the interrupt + //we need to disable the interrupt + } + + //now we need to set the pins to serial port peripheral (sercom0) + setPinMux(PIN_STEP_INPUT,PORT_PMUX_PMUXE_C_Val); + setPinMux(PIN_DIR_INPUT,PORT_PMUX_PMUXE_C_Val); + + //make sure that step pin is input with mux to peripheral + setPinCfg(PIN_STEP_INPUT, PORT_PINCFG_PMUXEN | PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); + + //make sure that dir pin is an output with mux to peripheral + setPinCfg(PIN_DIR_INPUT, PORT_PINCFG_PMUXEN ); + + Serial1.begin(STEP_DIR_BAUD); + + } + if (enableState == true && lastState==false) + { + Serial1.end(); + setPinMux(PIN_STEP_INPUT,pinMux[0]); + setPinMux(PIN_DIR_INPUT,pinMux[1]); + setPinCfg(PIN_STEP_INPUT,pinCFG[0]); + setPinCfg(PIN_DIR_INPUT,pinCFG[1]); + //turn step/dir pins back to GPIO + if (PORT_PMUX_PMUXE_A_Val == pinMux[0]) + { + //if interrupt was enabled for step pin renable it. + EExt_Interrupts in = g_APinDescription[PIN_STEP_INPUT].ulExtInt; + EIC->INTENSET.reg = EIC_INTENCLR_EXTINT(1 << in); //enable the interrupt + } + + } + +#endif //USE_STEP_DIR_SERIAL + lastState=enableState; +} + + + + + +void TC5_Handler() +{ +// static bool led=false; +// YELLOW_LED(led); +// led=!led; + interrupts(); //allow other interrupts + if (TC5->COUNT16.INTFLAG.bit.OVF == 1) + { + int error=0; + + + error=(stepperCtrl.processFeedback()); //handle the control loop + YELLOW_LED(error); +#ifdef PIN_ENABLE + GPIO_OUTPUT(PIN_ERROR); + bool level; + level = !NVM->SystemParams.errorLogic; + if (error) + { //assume high is inactive and low is active on error pin + digitalWrite(PIN_ERROR,level); + }else + { + digitalWrite(PIN_ERROR,!level); + } +#else + + if (NVM->SystemParams.errorPinMode == ERROR_PIN_MODE_ERROR) + { + GPIO_OUTPUT(PIN_ERROR); + if (error) + { //assume high is inactive and low is active on error pin + digitalWrite(PIN_ERROR,LOW); + }else + { + digitalWrite(PIN_ERROR,HIGH); + } + } +#endif + TC5->COUNT16.INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag + } + +} + +//check the NVM and set to defaults if there is any +void validateAndInitNVMParams(void) +{ + + if (false == NVM->sPID.parametersVaild) + { + nvmWrite_sPID(0.9,0.0001, 0.01); + } + + if (false == NVM->pPID.parametersVaild) + { + nvmWrite_pPID(1.0, 0, 0); + } + + if (false == NVM->vPID.parametersVaild) + { + nvmWrite_vPID(2.0, 1.0, 1.0); + } + + if (false == NVM->SystemParams.parametersVaild) + { + SystemParams_t params; + params.microsteps=16; + #if defined(CTRL_POS_PID_AS_DEFAULT) + params.controllerMode=CTRL_POS_PID; + #else + params.controllerMode=CTRL_SIMPLE; + #endif + + params.dirPinRotation=CW_ROTATION; //default to clockwise rotation when dir is high + params.errorLimit=(int32_t)ANGLE_FROM_DEGREES(1.8); + params.errorPinMode=ERROR_PIN_MODE_ENABLE; //default to enable pin + params.homePin=-1; + params.errorLogic=false; + params.homeAngleDelay=ANGLE_FROM_DEGREES(10); + nvmWriteSystemParms(params); + } + + //the motor parameters are check in the stepper_controller code + // as that there we can auto set much of them. + + +} + + + +void SYSCTRL_Handler(void) +{ + if (SYSCTRL->INTFLAG.reg & SYSCTRL_INTFLAG_BOD33DET) + { + eepromFlush(); //flush the eeprom + SYSCTRL->INTFLAG.reg |= SYSCTRL_INTFLAG_BOD33DET; + } +} + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncBOD33(void) __attribute__((always_inline, unused)); +static void syncBOD33(void) { + //int32_t t0=1000; + while (SYSCTRL->PCLKSR.bit.BOD33RDY==1) + { + // t0--; + // if (t0==0) + // { + // break; + // } + } +} +static void configure_bod(void) +{ + //syncBOD33(); + //SYSCTRL->BOD33.reg=0; //disable BOD33 before starting + //syncBOD33(); + SYSCTRL->BOD33.reg=SYSCTRL_BOD33_ACTION_INTERRUPT | //generate interrupt when BOD is triggered + SYSCTRL_BOD33_LEVEL(48) | //about 3.2V + //SYSCTRL_BOD33_HYST | //enable hysteresis + SYSCTRL_BOD33_ENABLE; //turn module on + + LOG("BOD33 %02X", SYSCTRL->BOD33.reg ); + SYSCTRL->INTENSET.reg |= SYSCTRL_INTENSET_BOD33DET; + + NVIC_SetPriority(SYSCTRL_IRQn, 1); //make highest priority as we need to save eeprom + // Enable InterruptVector + NVIC_EnableIRQ(SYSCTRL_IRQn); +} + + +void NZS::begin(void) +{ + int to=20; + stepCtrlError_t stepCtrlError; + + //set up the pins correctly on the board. + boardSetupPins(); + + //start up the USB serial interface + //TODO check for power on USB before doing this... +#ifndef MECHADUINO_HARDWARE + SerialUSB.begin(SERIAL_BAUD); +#endif + + //setup the serial port for syslog + Serial5.begin(SERIAL_BAUD); + + +#ifndef CMD_SERIAL_PORT + SysLogInit(&Serial5,LOG_DEBUG); + pinPeripheral(PIN_TXD, PIO_SERCOM_ALT); + pinPeripheral(PIN_RXD, PIO_SERCOM_ALT); +#else + SysLogInit(NULL, LOG_WARNING); +#endif + + LOG("Power up!"); + pinMode(PIN_USB_PWR, INPUT); + +#ifndef MECHADUINO_HARDWARE + if (digitalRead(PIN_USB_PWR)) + { + //wait for USB serial port to come alive + while (!SerialUSB) + { + to--; + if (to == 0) + { + break; + } + delay(500); + }; //wait for serial + } else + { + WARNING("USB Not connected"); + } +#endif + + validateAndInitNVMParams(); + + LOG("EEPROM INIT"); + if (EEPROM_OK == eepromInit()) //init the EEPROM + { + eepromRead((uint8_t *)&PowerupEEPROM, sizeof(PowerupEEPROM)); + } + configure_bod(); //configure the BOD +#ifndef DISABLE_LCD + LOG("Testing LCD"); + Lcd.begin(&stepperCtrl); + +#ifdef A5995_DRIVER + Lcd.lcdShow("MisfitTech","NEMA 23", VERSION); +#else + Lcd.lcdShow("MisfitTech","NEMA 17", VERSION); +#endif + +#endif + + LOG("command init!"); + commandsInit(); //setup command handler system + + + stepCtrlError=STEPCTRL_NO_CAL; + + + while (STEPCTRL_NO_ERROR != stepCtrlError) + { + LOG("init the stepper controller"); + stepCtrlError=stepperCtrl.begin(); //start controller before accepting step inputs + + //todo we need to handle error on LCD and through command line + if (STEPCTRL_NO_POWER == stepCtrlError) + { +#ifndef MECHADUINO_HARDWARE + SerialUSB.println("Appears that there is no Motor Power"); + SerialUSB.println("Connect motor power!"); +#else + Serial5.println("Appears that there is no Motor Power"); + Serial5.println("Connect motor power!"); +#endif +#ifndef DISABLE_LCD + Lcd.lcdShow("Waiting", "MOTOR", "POWER"); +#endif + while (STEPCTRL_NO_POWER == stepCtrlError) + { + stepCtrlError=stepperCtrl.begin(); //start controller before accepting step inputs + } + + } + + if (STEPCTRL_NO_CAL == stepCtrlError) + { +#ifndef MECHADUINO_HARDWARE + SerialUSB.println("You need to Calibrate"); +#else + Serial5.println("You need to Calibrate"); +#endif +#ifndef DISABLE_LCD + Lcd.lcdShow(" NOT ", "Calibrated", " "); + delay(1000); + Lcd.setMenu(MenuCal); + Lcd.forceMenuActive(); +#endif + + //TODO add code here for LCD and command line loop + while(false == stepperCtrl.calibrationValid()) + { + commandsProcess(); //handle commands + +#ifndef DISABLE_LCD + Lcd.process(); +#endif + + } + +#ifndef DISABLE_LCD + Lcd.setMenu(NULL); +#endif + } + + if (STEPCTRL_NO_ENCODER == stepCtrlError) + { +#ifndef MECHADUINO_HARDWARE + SerialUSB.println("AS5047D not working"); + SerialUSB.println(" try disconnecting power from board for 15+mins"); + SerialUSB.println(" you might have to short out power pins to ground"); +#else + Serial5.println("AS5047D not working"); + Serial5.println(" try disconnecting power from board for 15+mins"); + Serial5.println(" you might have to short out power pins to ground"); +#endif +#ifndef DISABLE_LCD + Lcd.lcdShow("Encoder", " Error!", " REBOOT"); +#endif + while(1) + { + + } + } + + } +#ifndef DISABLE_LCD + Lcd.setMenu(MenuMain); +#endif + + stepPinSetup(); //setup the step pin + +#ifdef PIN_ENABLE + //attachInterrupt(digitalPinToInterrupt(PIN_ENABLE), enableInput, CHANGE); + NVIC_SetPriority(EIC_IRQn, 0); //set port A interrupt as highest priority +#else + attachInterrupt(digitalPinToInterrupt(PIN_ERROR), enableInput, CHANGE); +#endif + + SmartPlanner.begin(&stepperCtrl); + RED_LED(false); + LOG("SETUP DONE!"); +} + + +void printLocation(void) +{ + char buf[128]={0}; + Location_t loc; + int32_t n, i, len; + int32_t pktSize; + + if (dataEnabled==0) + { + //RED_LED(false); + return; + } + + //the packet length for binary print is 12bytes + // assuming rate of 6Khz this would be 72,000 baud + i=0; + n=stepperCtrl.getLocation(&loc); + if (n==-1) + { + //RED_LED(false); + return; + } + + len=0; + pktSize=sizeof(Location_t)+1; //packet lenght is size location plus sync byte + + // //binary write + + while(n>=0 && (len)<=(128-pktSize)) + { + memcpy(&buf[len],&loc,sizeof(Location_t)); + len+=sizeof(Location_t); + buf[len]=0XAA; //sync + len++; + buf[len]=sizeof(Location_t); //data len + len++; + + n=stepperCtrl.getLocation(&loc); + i++; + } +#ifndef MECHADUINO_HARDWARE + SerialUSB.write(buf,len); +#endif + + //hex write + // hex write is 29 bytes per tick, @ 6khz this 174000 baud + // while(n>=0 && (i*29)<(200-29)) + // { + // sprintf(buf,"%s%08X\t%08X\t%08X\n\r",buf,loc.microSecs,loc.desiredLoc,loc.actualLoc); + // n=stepperCtrl.getLocation(&loc); + // i++; + // } + // SerialUSB.write(buf,strlen(buf)); + +// if (n<=0) +// { +// RED_LED(false); +// }else +// { +// RED_LED(true); +// } + + return; +} + +void NZS::loop(void) +{ + eepromData_t eepromData; + + + // if (dataEnabled==0) + // { + // LOG("loop time is %dus",stepperCtrl.getLoopTime()); + // } + + //read the enable pin and update + // this is also done as an edge interrupt but does not always see + // to trigger the ISR. + enableInput(); + + if (enableState != stepperCtrl.getEnable()) + { + stepperCtrl.enable(enableState); + } + + //handle EEPROM + eepromData.angle=stepperCtrl.getCurrentAngle(); + eepromData.encoderAngle=stepperCtrl.getEncoderAngle(); + eepromData.valid=1; + eepromWriteCache((uint8_t *)&eepromData,sizeof(eepromData)); + + commandsProcess(); //handle commands +#ifndef DISABLE_LCD + Lcd.process(); +#endif + //stepperCtrl.PrintData(); //prints steps and angle to serial USB. + + + printLocation(); //print out the current location + + return; +} + +#pragma GCC pop_options diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.h b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.h new file mode 100644 index 0000000..a21904d --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.h @@ -0,0 +1,53 @@ +/* + * nzs.h + * + * Created on: Dec 8, 2016 + * Author: trampas + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#ifndef NZS_H_ +#define NZS_H_ + +#include "board.h" +#include "nzs_lcd.h" +#include "stepper_controller.h" +#include "planner.h" + +typedef struct +{ + int64_t angle; + uint16_t encoderAngle; + uint8_t valid; +}eepromData_t; + +class NZS //nano Zero Stepper +{ + + public: + void begin(void); + void loop(void); + +}; + + +#endif /* NZS_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.cpp new file mode 100644 index 0000000..b29051c --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.cpp @@ -0,0 +1,600 @@ +/* + * nzs_lcd.cpp + * + * Created on: Dec 8, 2016 + * Author: trampas + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#include "nzs_lcd.h" +#include +#include +#include + + +#ifndef DISABLE_LCD +void LCD::begin(StepperCtrl *ptrsCtrl) +{ +#ifndef MECHADUINO_HARDWARE + pinMode(PIN_SW1, INPUT_PULLUP); + pinMode(PIN_SW3, INPUT_PULLUP); + pinMode(PIN_SW4, INPUT_PULLUP); +#endif + buttonState=0; + + //we need access to the stepper controller + ptrStepperCtrl=ptrsCtrl; //save a pointer to the stepper controller + + + ptrMenu=NULL; + menuIndex=0; + menuActive=false; + optionIndex=0; + ptrOptions=NULL; + displayEnabled=true; + + //check that the SCL and SDA are pulled high + pinMode(PIN_SDA, INPUT); + pinMode(PIN_SCL, INPUT); + if (digitalRead(PIN_SDA)==0) + { + //pin is not pulled up + displayEnabled=false; + } + if (digitalRead(PIN_SCL)==0) + { + //pin is not pulled up + displayEnabled=false; + } + + if (displayEnabled) + { + displayEnabled=display.begin(SSD1306_SWITCHCAPVCC, 0x3C); + }else + { + WARNING("SCL/SDA not pulled up"); + } + if (false == displayEnabled) + { + WARNING("NO display found, LCD will not be used"); + } + Wire.setClock(800000); + + //showSplash(); + +} + + +void __attribute__ ((optimize("Ofast"))) LCD::lcdShow(const char *line1, const char *line2,const char *line3) +{ + + if (false == displayEnabled) + { + return; + } + display.clearDisplay(); + display.setTextSize(2); + display.setTextColor(WHITE); + display.setCursor(0,0); + display.println(line1); + display.setCursor(0,20); + display.println(line2); + display.setCursor(0,40); + display.println(line3); + display.display(); + +} + +void LCD::showSplash(void) +{ + if (false == displayEnabled) + { + return; + } +#ifdef A5995_DRIVER + lcdShow("MisfitTech","NEMA 23", VERSION); +#else + lcdShow("MisfitTech","NEMA 17", VERSION); +#endif +} + + +void LCD::setMenu(menuItem_t *pMenu) +{ + if (false == displayEnabled) + { + return; + } + ptrMenu=pMenu; + menuIndex=0; +} + + +void LCD::showOptions(void) +{ + int32_t i,j; + char str[3][26]={0}; + if (false == displayEnabled) + { + return; + } + + i=optionIndex; + j=0; + while(strlen(ptrOptions[i].str)>0 && j<3) + { + if (i == optionIndex) + { + sprintf(str[j],"*%s",ptrOptions[i].str); + }else + { + sprintf(str[j]," %s",ptrOptions[i].str); + } + j++; + i++; + } + + lcdShow(str[0], str[1], str[2]); + + return; +} + + +void __attribute__ ((optimize("Ofast"))) LCD::showMenu(void) +{ + int32_t i,j; + char str[3][26]={0}; + if (false == displayEnabled) + { + return; + } + + i=menuIndex; + j=0; + while(ptrMenu[i].func!=NULL && j<3) + { + if (i == menuIndex) + { + sprintf(str[j],"*%s",ptrMenu[i].str); + }else + { + sprintf(str[j]," %s",ptrMenu[i].str); + } + j++; + i++; + } + + //show exit if there is room + if (j<3) + { + if (j==0) + { + sprintf(str[j],"*Exit"); + }else + { + sprintf(str[j]," Exit"); + } + } + + lcdShow(str[0], str[1], str[2]); + + + return; +} + + +void __attribute__ ((optimize("Ofast"))) LCD::updateMenu(void) +{ + if (false == displayEnabled) + { + return; + } + + if (ptrOptions != NULL) + { + showOptions(); + }else + { + showMenu(); + } + + //handle push buttons + if (digitalRead(PIN_SW3)==0 && (buttonState & 0x02)==0) + { + buttonState |= 0x02; + + LOG("SW3 pressed"); + if (ptrMenu[menuIndex].func == NULL) + { + //exit pressed + menuIndex=0; //reset menu index + menuActive=false; + return; + } + + if (ptrMenu[menuIndex].func != NULL) + { + LOG("Calling function for %s",ptrMenu[menuIndex].str); + if (ptrOptions != NULL) + { + char *ptrArgV[1]; + char str[25]={0}; + ptrArgV[0]=str; + sprintf(str,"%d",optionIndex); + LOG("Calling function for %s %s",ptrMenu[menuIndex].str,str); + ptrMenu[menuIndex].func(1,ptrArgV); + ptrOptions=NULL; + optionIndex=0; + }else + { + int i; + i=ptrMenu[menuIndex].func(0,NULL); + if (ptrMenu[menuIndex].ptrOptions != NULL) + { + LOG("displaying options for %s %d",ptrMenu[menuIndex].str,i); + ptrOptions=ptrMenu[menuIndex].ptrOptions; + optionIndex=i; + } + } + + return; + } + + } + if (digitalRead(PIN_SW1)==0 && (buttonState & 0x01)==0) + { + buttonState |= 0x01; + LOG("SW1 pressed"); + if (ptrOptions != NULL) + { + optionIndex++; + if (strlen(ptrOptions[optionIndex].str) == 0) + { + optionIndex=0; + } + } else + { + if (ptrMenu[menuIndex].func != NULL) + { + menuIndex++; + } else + { + menuIndex=0; + } + } + + } + + if (digitalRead(PIN_SW1)) + { + buttonState &= ~0x01; + } + + if (digitalRead(PIN_SW3)) + { + buttonState &= ~0x02; + } +} + +void LCD::forceMenuActive(void) +{ + + menuActive=true; +} + +void __attribute__((optimize("Ofast")))LCD::process(void) +{ + if (false == displayEnabled) + { + return; + } + + if (false == menuActive || ptrMenu==NULL) + { + updateLCD(); + }else + { + updateMenu(); + } + + if (digitalRead(PIN_SW4)==0 && (buttonState & 0x04)==0) + { + buttonState |= 0x04; + menuActive=!menuActive; + } + + if (digitalRead(PIN_SW4)) + { + buttonState &= ~0x04; + } +} +#endif +/* +//does the LCD menu system +void StepperCtrl::menu(void) +{ + + bool done=false; + int menuItem=0; + char str[100]; + int sw1State=0; + int sw3State=0; + + pinMode(PIN_SW1, INPUT_PULLUP); + pinMode(PIN_SW3, INPUT_PULLUP); + pinMode(PIN_SW4, INPUT_PULLUP); + + + while (!done) + { + display.clearDisplay(); + display.setTextSize(2); + display.setTextColor(WHITE); + + if (menuItem==0) + { + sprintf(str,"*Run Cal"); + display.setCursor(0,0); + display.println(str); + }else + { + sprintf(str," Run Cal"); + display.setCursor(0,0); + display.println(str); + } + + if (menuItem==1) + { + sprintf(str,"*Check Cal"); + display.setCursor(0,20); + display.println(str); + }else + { + sprintf(str," Check Cal"); + display.setCursor(0,20); + display.println(str); + } + + if (menuItem==2) + { + sprintf(str,"*Exit"); + display.setCursor(0,40); + display.println(str); + }else + { + sprintf(str," Exit"); + display.setCursor(0,40); + display.println(str); + } + + display.display(); + + if (sw1State==1) + { + while (digitalRead(PIN_SW1)==0); + sw1State=0; + } + + if (digitalRead(PIN_SW1)==0) + { + sw1State=1; + menuItem=(menuItem+1)%3; + } + + if (sw3State==1) + { + while (digitalRead(PIN_SW3)==0); + sw3State=0; + } + + if (digitalRead(PIN_SW3)==0) + { + sw3State=1; + switch(menuItem) + { + case 0: + display.clearDisplay(); + display.setTextSize(2); + display.setTextColor(WHITE); + display.setCursor(0,0); + display.println("Running"); + display.setCursor(0,20); + display.println("Cal"); + display.display(); + calibrateEncoder(); + break; + case 1: + { + display.clearDisplay(); + display.setTextSize(2); + display.setTextColor(WHITE); + display.setCursor(0,0); + display.println("Testing"); + display.setCursor(0,20); + display.println("Cal"); + display.display(); + int32_t error,x,y,m; + error=maxCalibrationError(); + x=(error*100 *360)/ANGLE_STEPS; + m=x/100; + y=abs(x-(m*100)); + display.clearDisplay(); + display.setTextSize(2); + display.setTextColor(WHITE); + display.setCursor(0,0); + display.println("Error"); + + sprintf(str, "%02d.%02d deg",m,y); + display.setCursor(0,20); + display.println(str); + display.display(); + while (digitalRead(PIN_SW3)); + break; + } + case 2: + return; + break; + + } + + } + + } + +} + + */ + +void LCD::updateLCD(void) +{ + if (false == displayEnabled) + { + return; + } + char str[3][25]; + static int highRPM=0; + int32_t y,z,err; + + static int64_t lastAngle,deg; + static int32_t RPM=0; + static int32_t lasttime=0; + + bool state; + static int32_t dt=40; + static uint32_t t0=0; + + static bool rpmDone=false; + + if ((millis()-t0)>500) + { + + int32_t x,d; + + //do first half of RPM measurement + if (!rpmDone) + { + //LOG("loop time is %dus",ptrStepperCtrl->getLoopTime()); + lastAngle=ptrStepperCtrl->getCurrentAngle(); + lasttime=millis(); + rpmDone=true; + return; + } + + //do the second half of rpm measurement and update LCD. + if (rpmDone && (millis()-lasttime)>(dt)) + { + rpmDone=false; + deg=ptrStepperCtrl->getCurrentAngle(); + y=millis()-lasttime; + err=ptrStepperCtrl->getLoopError(); + + t0=millis(); + d=(int64_t)(lastAngle-deg); + + d=abs(d); + + x=0; + if (d>0) + { + x=((int64_t)d*(60*1000UL))/((int64_t)y * ANGLE_STEPS); + } + + lastAngle=deg; + RPM=(int32_t)x; //(7*RPM+x)/8; //average RPMs + if (RPM>500) + { + dt=10; + } + if (RPM<100) + { + dt=100; + } + str[0][0]='\0'; + //LOG("RPMs is %d, %d, %d",(int32_t)x,(int32_t)d,(int32_t)y); + switch(ptrStepperCtrl->getControlMode()) + { + case CTRL_SIMPLE: + sprintf(str[0], "%dRPM simp",RPM); + break; + case CTRL_TORQUE: + sprintf(str[0], "%dRPM torque",RPM); + break; + case CTRL_POS_PID: + sprintf(str[0], "%dRPM pPID",RPM); + break; + case CTRL_POS_VELOCITY_PID: + sprintf(str[0], "%dRPM vPID",RPM); + break; + case CTRL_OPEN: + sprintf(str[0], "%dRPM open",RPM); + break; + case CTRL_OFF: + sprintf(str[0], "%dRPM off",RPM); + break; + default: + sprintf(str[0], "error %u",ptrStepperCtrl->getControlMode()); + break; + + } + + + err=(err*360*100)/(int32_t)ANGLE_STEPS; + //LOG("error is %d %d %d",err,(int32_t)ptrStepperCtrl->getCurrentLocation(),(int32_t)ptrStepperCtrl->getDesiredLocation()); + z=(err)/100; + y=abs(err-(z*100)); + + sprintf(str[1],"%01d.%02d err", z,y); + + + deg=ptrStepperCtrl->getDesiredAngle(); + +#ifndef NZS_LCD_ABSOULTE_ANGLE + deg=deg & ANGLE_MAX; //limit to 360 degrees +#endif + + deg=(deg*360*10)/(int32_t)ANGLE_STEPS; + int K=0; + if (abs(deg)>9999) + { + K=1; + deg=deg/1000; + } + + x=(deg)/10; + y=abs(deg-(x*10)); + + if (K==1) + { + sprintf(str[2],"%03d.%01uKdeg", x,y); + }else + { + sprintf(str[2],"%03d.%01udeg", x,y); + } + str[0][10]='\0'; + str[1][10]='\0'; + str[2][10]='\0'; + lcdShow(str[0],str[1],str[2]); + } + } +} + + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.h b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.h new file mode 100644 index 0000000..c3c4bac --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.h @@ -0,0 +1,90 @@ +/* + * nzs_lcd.h + * + * Created on: Dec 8, 2016 + * Author: trampas + * + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#ifndef NZS_LCD_H_ +#define NZS_LCD_H_ + +#include "Arduino.h" +#include "syslog.h" +#include "board.h" +#include "stepper_controller.h" + +#include "Adafruit_GFX.h" +#include "Adafruit_SSD1306.h" +#include "gfxfont.h" + + +typedef struct { + char str[15]; +} options_t; + +typedef struct { + char str[15]; + + //only one of the following should be not null + int (*func)(int argc, char *argv[]); + options_t *ptrOptions; + +} menuItem_t; + + + + + +class LCD +{ + private: + bool displayEnabled; + Adafruit_SSD1306 display; + StepperCtrl *ptrStepperCtrl; + menuItem_t *ptrMenu; + int32_t menuIndex; + bool menuActive; + + options_t *ptrOptions; + int32_t optionIndex; + + int32_t buttonState; + + void updateLCD(void); + void showMenu(void); + void updateMenu(void); + void showOptions(void); + public: + void forceMenuActive(void); + void setMenu(menuItem_t *pMenu); + void begin(StepperCtrl *ptrStepperCtrl); //sets up the LCD + void process(void); //processes the LCD and updates as needed + void showSplash(void); + void lcdShow(const char *line1, const char *line2,const char *line3); + + +}; + + +#endif /* NZS_LCD_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/planner.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/planner.cpp new file mode 100644 index 0000000..ec37836 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/planner.cpp @@ -0,0 +1,207 @@ +/********************************************************************** + * Author: tstern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "planner.h" + +#include "board.h" +#include "wiring_private.h" +#include "syslog.h" +#include "angle.h" +#include "Arduino.h" + +#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY); + +//define the planner class as being global +Planner SmartPlanner; + +static bool enterTC3CriticalSection() +{ + bool state=NVIC_IS_IRQ_ENABLED(TC3_IRQn); + NVIC_DisableIRQ(TC3_IRQn); + return state; +} + +static void exitTC3CriticalSection(bool prevState) +{ + if (prevState) + { + NVIC_EnableIRQ(TC3_IRQn); + } //else do nothing +} + + + + +void TC3_Init(void) +{ + // Enable GCLK for TC3 + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ; + while (GCLK->STATUS.bit.SYNCBUSY); + + TC3->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; // Disable TCx + WAIT_TC16_REGS_SYNC(TC3) // wait for sync + + TC3->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16; // Set Timer counter Mode to 16 bits + WAIT_TC16_REGS_SYNC(TC3) + + TC3->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ; // Set TC as normal Normal Frq + WAIT_TC16_REGS_SYNC(TC3) + + TC3->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV2; // Set perscaler + WAIT_TC16_REGS_SYNC(TC3) + + + TC3->COUNT16.CC[0].reg = F_CPU/PLANNER_UPDATE_RATE_HZ/2; //divide by two because of prescaler + + WAIT_TC16_REGS_SYNC(TC3) + + + TC3->COUNT16.INTENSET.reg = 0; // disable all interrupts + TC3->COUNT16.INTENSET.bit.OVF = 1; // enable overfollow + + + + NVIC_SetPriority(TC3_IRQn, 3); + + + // Enable InterruptVector + NVIC_EnableIRQ(TC3_IRQn); + + + // Enable TC + TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; + WAIT_TC16_REGS_SYNC(TC3); +} + + +void TC3_Handler(void) +{ + interrupts(); //allow other interrupts + //do the planner tick + SmartPlanner.tick(); + //SerialUSB.println('x'); + TC3->COUNT16.INTFLAG.bit.OVF = 1; //clear interrupt by writing 1 to flag +} + +void Planner::begin(StepperCtrl *ptrStepper) +{ + + ptrStepperCtrl=ptrStepper; + currentMode=PLANNER_NONE; + //setup the timer and interrupt as the last thing + TC3_Init(); +} + +void Planner::tick(void) +{ + if (currentMode == PLANNER_NONE) + { + return; //do nothing + } + + if (PLANNER_CV == currentMode) + { +// SerialUSB.println(currentSetAngle); +// SerialUSB.println(endAngle); +// SerialUSB.println(tickIncrement); +// SerialUSB.println(fabs(currentSetAngle-endAngle)); +// SerialUSB.println(fabs(tickIncrement*2)); +// SerialUSB.println(); + int32_t x; + if (fabs(currentSetAngle-endAngle) >= fabs(tickIncrement)) + { + currentSetAngle+=tickIncrement; + x=ANGLE_FROM_DEGREES(currentSetAngle); + ptrStepperCtrl->moveToAbsAngle(x); + }else + { + //we are done, make sure we end at the right point + //SerialUSB.println("done"); + x=ANGLE_FROM_DEGREES(endAngle); + ptrStepperCtrl->moveToAbsAngle(x); + currentMode=PLANNER_NONE; + } + } + + +} + +void Planner::stop(void) +{ + bool state; + state = enterTC3CriticalSection(); + currentMode=PLANNER_NONE; + exitTC3CriticalSection(state); +} + +bool Planner::moveConstantVelocity(float finalAngle, float rpm) +{ + bool state; + state = enterTC3CriticalSection(); + + //first determine if operation is in progress + if (PLANNER_NONE != currentMode) + { +#ifndef MECHADUINO_HARDWARE + //we are in operation return false + SerialUSB.println("planner operational"); +#else + Serial5.println("planner operational"); +#endif + exitTC3CriticalSection(state); + return false; + } + + //get current posistion + startAngle = ANGLE_T0_DEGREES(ptrStepperCtrl->getCurrentAngle()); + + //deterime the tick increment + tickIncrement=360.0*fabs(rpm)/60/PLANNER_UPDATE_RATE_HZ; + + + + //set the desired end angle + endAngle=finalAngle; + + + //set the current angle + currentSetAngle=startAngle; + + if (startAngle>endAngle) + { +#ifndef MECHADUINO_HARDWARE + SerialUSB.println("reverse"); +#endif + tickIncrement=-tickIncrement; + } + +// SerialUSB.println(currentSetAngle); +// SerialUSB.println(endAngle); +// SerialUSB.println(tickIncrement); +// SerialUSB.println(); + + currentMode=PLANNER_CV; + + exitTC3CriticalSection(state); + return true; +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/planner.h b/firmware_smartstepper_trikarus/stepper_nano_zero/planner.h new file mode 100644 index 0000000..e80b8b1 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/planner.h @@ -0,0 +1,68 @@ +/********************************************************************** + * Author: tstern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +/* + * This file implements a trajectory planner for use with serial + * interface. It allows the smart stepper to move at constant velocity. + * Additionally you can move to some location at constant velocity or + * with a trajectory curve + */ + +#ifndef PLANNER_H_ +#define PLANNER_H_ +#include "board.h" +#include "stepper_controller.h" + +#define PLANNER_UPDATE_RATE_HZ (3000UL) //how often planner updates PID + +typedef enum { + PLANNER_NONE =0, + PLANNER_CV =1, //constant velocity + //PLANNER_CA =2, //constant accleration + //PLANNER_S_CURVE =3, //s-curve move +} PlannerMode; +class Planner +{ + private: + StepperCtrl *ptrStepperCtrl; + volatile PlannerMode currentMode=PLANNER_NONE; + //todo we should not use floating point, rather use "Angle" + volatile float endAngle; + volatile float startAngle; + volatile float currentSetAngle; + volatile float tickIncrement; + + public: + void begin(StepperCtrl *ptrStepper); + bool moveConstantVelocity(float finalAngle, float rpm); //moves to the final location at a constant RPM + void tick(void); //this is called on regular tick interval + void stop(void); + bool done(void) {return currentMode==PLANNER_NONE;} +}; + + +extern Planner SmartPlanner; + + +#endif /* PLANNER_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/sine.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/sine.cpp new file mode 100644 index 0000000..8c2e22c --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/sine.cpp @@ -0,0 +1,198 @@ +/* + * since.cpp + * + * Created on: Dec 24, 2016 + * Author: tstern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#include "sine.h" + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + +#ifdef NZS_FAST_SINE +static const int16_t sineTable[1280]={ +0,201,402,603,804,1005,1206,1407,1608,1808,2009,2210,2410,2611,2811,3011, +3212,3412,3611,3811,4011,4210,4410,4609,4808,5007,5205,5404,5602,5800,5998,6195, +6392,6589,6786,6983,7179,7375,7571,7766,7962,8156,8351,8545,8739,8933,9126,9319, +9512,9704,9896,10087,10278,10469,10659,10849,11039,11228,11417,11605,11793,11980,12167,12353, +12539,12725,12910,13094,13278,13462,13645,13828,14010,14191,14372,14553,14732,14912,15090,15269, +15446,15623,15800,15976,16151,16325,16499,16673,16846,17018,17189,17360,17530,17700,17869,18037, +18204,18371,18537,18703,18868,19032,19195,19357,19519,19680,19841,20000,20159,20317,20475,20631, +20787,20942,21097,21250,21403,21554,21705,21856,22005,22154,22301,22448,22594,22739,22884,23027, +23170,23312,23452,23592,23732,23870,24007,24143,24279,24413,24547,24680,24812,24942,25072,25201, +25329,25456,25583,25708,25832,25955,26077,26199,26319,26438,26556,26674,26790,26905,27019,27133, +27245,27356,27466,27575,27683,27791,27897,28001,28105,28208,28310,28411,28510,28609,28706,28803, +28898,28992,29085,29178,29268,29358,29447,29535,29621,29707,29791,29874,29956,30037,30117,30195, +30273,30349,30425,30499,30572,30643,30714,30783,30852,30919,30985,31050,31113,31176,31237,31297, +31356,31414,31471,31526,31580,31633,31685,31736,31785,31834,31881,31926,31971,32015,32057,32098, +32138,32176,32214,32250,32285,32319,32351,32382,32413,32441,32469,32496,32521,32545,32568,32589, +32609,32629,32646,32663,32678,32693,32706,32717,32728,32737,32745,32752,32757,32762,32765,32767, +32767,32767,32765,32762,32757,32752,32745,32737,32728,32717,32706,32693,32678,32663,32646,32629, +32609,32589,32568,32545,32521,32496,32469,32441,32413,32382,32351,32319,32285,32250,32214,32176, +32138,32098,32057,32015,31971,31926,31881,31834,31785,31736,31685,31633,31580,31526,31471,31414, +31356,31297,31237,31176,31113,31050,30985,30919,30852,30783,30714,30643,30572,30499,30425,30349, +30273,30195,30117,30037,29956,29874,29791,29707,29621,29535,29447,29358,29268,29178,29085,28992, +28898,28803,28706,28609,28510,28411,28310,28208,28105,28001,27897,27791,27683,27575,27466,27356, +27245,27133,27019,26905,26790,26674,26556,26438,26319,26199,26077,25955,25832,25708,25583,25456, +25329,25201,25072,24942,24812,24680,24547,24413,24279,24143,24007,23870,23732,23592,23452,23312, +23170,23027,22884,22739,22594,22448,22301,22154,22005,21856,21705,21554,21403,21250,21097,20942, +20787,20631,20475,20317,20159,20000,19841,19680,19519,19357,19195,19032,18868,18703,18537,18371, +18204,18037,17869,17700,17530,17360,17189,17018,16846,16673,16499,16325,16151,15976,15800,15623, +15446,15269,15090,14912,14732,14553,14372,14191,14010,13828,13645,13462,13278,13094,12910,12725, +12539,12353,12167,11980,11793,11605,11417,11228,11039,10849,10659,10469,10278,10087,9896,9704, +9512,9319,9126,8933,8739,8545,8351,8156,7962,7766,7571,7375,7179,6983,6786,6589, +6392,6195,5998,5800,5602,5404,5205,5007,4808,4609,4410,4210,4011,3811,3611,3412, +3212,3011,2811,2611,2410,2210,2009,1808,1608,1407,1206,1005,804,603,402,201, +0,-201,-402,-603,-804,-1005,-1206,-1407,-1608,-1809,-2010,-2210,-2411,-2611,-2812,-3012, +-3212,-3412,-3612,-3812,-4011,-4211,-4410,-4609,-4808,-5007,-5206,-5404,-5602,-5800,-5998,-6196, +-6393,-6590,-6787,-6983,-7180,-7376,-7571,-7767,-7962,-8157,-8352,-8546,-8740,-8933,-9127,-9320, +-9512,-9704,-9896,-10088,-10279,-10470,-10660,-10850,-11039,-11228,-11417,-11605,-11793,-11980,-12167,-12354, +-12540,-12725,-12910,-13095,-13279,-13463,-13646,-13828,-14010,-14192,-14373,-14553,-14733,-14912,-15091,-15269, +-15447,-15624,-15800,-15976,-16151,-16326,-16500,-16673,-16846,-17018,-17190,-17361,-17531,-17700,-17869,-18037, +-18205,-18372,-18538,-18703,-18868,-19032,-19195,-19358,-19520,-19681,-19841,-20001,-20160,-20318,-20475,-20632, +-20788,-20943,-21097,-21250,-21403,-21555,-21706,-21856,-22006,-22154,-22302,-22449,-22595,-22740,-22884,-23028, +-23170,-23312,-23453,-23593,-23732,-23870,-24007,-24144,-24279,-24414,-24548,-24680,-24812,-24943,-25073,-25202, +-25330,-25457,-25583,-25708,-25832,-25956,-26078,-26199,-26319,-26439,-26557,-26674,-26790,-26906,-27020,-27133, +-27245,-27357,-27467,-27576,-27684,-27791,-27897,-28002,-28106,-28209,-28310,-28411,-28511,-28609,-28707,-28803, +-28899,-28993,-29086,-29178,-29269,-29359,-29448,-29535,-29622,-29707,-29791,-29875,-29957,-30038,-30117,-30196, +-30273,-30350,-30425,-30499,-30572,-30644,-30715,-30784,-30852,-30919,-30985,-31050,-31114,-31176,-31238,-31298, +-31357,-31415,-31471,-31527,-31581,-31634,-31686,-31736,-31786,-31834,-31881,-31927,-31972,-32015,-32057,-32098, +-32138,-32177,-32214,-32250,-32285,-32319,-32352,-32383,-32413,-32442,-32470,-32496,-32521,-32545,-32568,-32590, +-32610,-32629,-32647,-32664,-32679,-32693,-32706,-32718,-32728,-32738,-32746,-32752,-32758,-32762,-32765,-32767, +-32768,-32767,-32765,-32762,-32758,-32752,-32746,-32738,-32728,-32718,-32706,-32693,-32679,-32664,-32647,-32629, +-32610,-32590,-32568,-32545,-32521,-32496,-32470,-32442,-32413,-32383,-32352,-32319,-32285,-32250,-32214,-32177, +-32138,-32098,-32057,-32015,-31972,-31927,-31881,-31834,-31786,-31736,-31686,-31634,-31581,-31527,-31471,-31415, +-31357,-31298,-31238,-31176,-31114,-31050,-30985,-30919,-30852,-30784,-30715,-30644,-30572,-30499,-30425,-30350, +-30273,-30196,-30117,-30038,-29957,-29875,-29791,-29707,-29622,-29535,-29448,-29359,-29269,-29178,-29086,-28993, +-28899,-28803,-28707,-28609,-28511,-28411,-28310,-28209,-28106,-28002,-27897,-27791,-27684,-27576,-27467,-27357, +-27245,-27133,-27020,-26906,-26790,-26674,-26557,-26439,-26319,-26199,-26078,-25956,-25832,-25708,-25583,-25457, +-25330,-25202,-25073,-24943,-24812,-24680,-24548,-24414,-24279,-24144,-24007,-23870,-23732,-23593,-23453,-23312, +-23170,-23028,-22884,-22740,-22595,-22449,-22302,-22154,-22006,-21856,-21706,-21555,-21403,-21250,-21097,-20943, +-20788,-20632,-20475,-20318,-20160,-20001,-19841,-19681,-19520,-19358,-19195,-19032,-18868,-18703,-18538,-18372, +-18205,-18037,-17869,-17700,-17531,-17361,-17190,-17018,-16846,-16673,-16500,-16326,-16151,-15976,-15800,-15624, +-15447,-15269,-15091,-14912,-14733,-14553,-14373,-14192,-14010,-13828,-13646,-13463,-13279,-13095,-12910,-12725, +-12540,-12354,-12167,-11980,-11793,-11605,-11417,-11228,-11039,-10850,-10660,-10470,-10279,-10088,-9896,-9704, +-9512,-9320,-9127,-8933,-8740,-8546,-8352,-8157,-7962,-7767,-7571,-7376,-7180,-6983,-6787,-6590, +-6393,-6196,-5998,-5800,-5602,-5404,-5206,-5007,-4808,-4609,-4410,-4211,-4011,-3812,-3612,-3412, +-3212,-3012,-2812,-2611,-2411,-2210,-2010,-1809,-1608,-1407,-1206,-1005,-804,-603,-402,-201, +0,201,402,603,804,1005,1206,1407,1608,1808,2009,2210,2410,2611,2811,3011, +3212,3412,3611,3811,4011,4210,4410,4609,4808,5007,5205,5404,5602,5800,5998,6195, +6392,6589,6786,6983,7179,7375,7571,7766,7962,8156,8351,8545,8739,8933,9126,9319, +9512,9704,9896,10087,10278,10469,10659,10849,11039,11228,11417,11605,11793,11980,12167,12353, +12539,12725,12910,13094,13278,13462,13645,13828,14010,14191,14372,14553,14732,14912,15090,15269, +15446,15623,15800,15976,16151,16325,16499,16673,16846,17018,17189,17360,17530,17700,17869,18037, +18204,18371,18537,18703,18868,19032,19195,19357,19519,19680,19841,20000,20159,20317,20475,20631, +20787,20942,21097,21250,21403,21554,21705,21856,22005,22154,22301,22448,22594,22739,22884,23027, +23170,23312,23452,23592,23732,23870,24007,24143,24279,24413,24547,24680,24812,24942,25072,25201, +25329,25456,25583,25708,25832,25955,26077,26199,26319,26438,26556,26674,26790,26905,27019,27133, +27245,27356,27466,27575,27683,27791,27897,28001,28105,28208,28310,28411,28510,28609,28706,28803, +28898,28992,29085,29178,29268,29358,29447,29535,29621,29707,29791,29874,29956,30037,30117,30195, +30273,30349,30425,30499,30572,30643,30714,30783,30852,30919,30985,31050,31113,31176,31237,31297, +31356,31414,31471,31526,31580,31633,31685,31736,31785,31834,31881,31926,31971,32015,32057,32098, +32138,32176,32214,32250,32285,32319,32351,32382,32413,32441,32469,32496,32521,32545,32568,32589, +32609,32629,32646,32663,32678,32693,32706,32717,32728,32737,32745,32752,32757,32762,32765,32767 +}; +#else +static const uint16_t sineTable[257]={ + 0,402,804,1206,1608,2010,2412,2814,3216,3617,4019,4420,4821,5222,5623,6023, + 6424,6824,7223,7623,8022,8421,8820,9218,9616,10014,10411,10808,11204,11600,11996,12391, + 12785,13179,13573,13966,14359,14751,15142,15533,15924,16313,16703,17091,17479,17866,18253,18639, + 19024,19408,19792,20175,20557,20939,21319,21699,22078,22456,22834,23210,23586,23960,24334,24707, + 25079,25450,25820,26189,26557,26925,27291,27656,28020,28383,28745,29106,29465,29824,30181,30538, + 30893,31247,31600,31952,32302,32651,32999,33346,33692,34036,34379,34721,35061,35400,35738,36074, + 36409,36743,37075,37406,37736,38064,38390,38715,39039,39361,39682,40001,40319,40635,40950,41263, + 41575,41885,42194,42500,42806,43109,43411,43712,44011,44308,44603,44897,45189,45479,45768,46055, + 46340,46624,46905,47185,47464,47740,48014,48287,48558,48827,49095,49360,49624,49885,50145,50403, + 50659,50913,51166,51416,51664,51911,52155,52398,52638,52877,53113,53348,53580,53811,54039,54266, + 54490,54713,54933,55151,55367,55582,55794,56003,56211,56417,56620,56822,57021,57218,57413,57606, + 57797,57985,58171,58356,58537,58717,58895,59070,59243,59414,59582,59749,59913,60075,60234,60391, + 60546,60699,60850,60998,61144,61287,61429,61567,61704,61838,61970,62100,62227,62352,62475,62595, + 62713,62829,62942,63053,63161,63267,63371,63472,63571,63668,63762,63853,63943,64030,64114,64196, + 64276,64353,64428,64500,64570,64638,64703,64765,64826,64883,64939,64992,65042,65090,65136,65179, + 65219,65258,65293,65327,65357,65386,65412,65435,65456,65475,65491,65504,65515,65524,65530,65534, + 65535, +}; +#endif + + + + +int16_t sine(uint16_t angle) +{ +#ifdef NZS_FAST_SINE + return sineTable[angle]; +#else + int sign=1; + int16_t ret; + //our sine table has 1024 points per rotation so convert angle to closest step + + if (angle>=(SINE_STEPS/2)) + { + sign=-1; + } + + angle=angle % (SINE_STEPS/2); //limit to 0-180 as sign takes care of 180-360 + + if (angle>(SINE_STEPS/4-1)) //if we are greater than 90 we need to look up table backwards + { + angle=(SINE_STEPS/2)-angle; + } + + ret=(int16_t)(sineTable[angle]/2)*sign; + return ret; +#endif +} + +int16_t cosine(uint16_t angle) +{ +#ifdef NZS_FAST_SINE + angle=angle+(SINE_STEPS/4); + return sineTable[angle]; +#else + + int sign=1; + int16_t ret; + //our sine table has 1024 points per rotation so convert angle to closest step + + if (angle>=(SINE_STEPS/4) and angle<(3*(SINE_STEPS/4))) + { + sign=-1; + } + + angle=angle % (SINE_STEPS/2); //limit to 0-180 as sign takes care of 180-360 + + if (angle>(SINE_STEPS/4-1)) //if we are greater than 90 we need to look up table backwards + { + angle=(SINE_STEPS/2)-angle; + } + + //for cosine we need 90 degree phase shift + angle=(SINE_STEPS/4)-angle; + + ret=(int16_t)(sineTable[angle]/2)*sign; + return ret; +#endif +} + +#pragma GCC pop_options diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/sine.h b/firmware_smartstepper_trikarus/stepper_nano_zero/sine.h new file mode 100644 index 0000000..8a039e4 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/sine.h @@ -0,0 +1,43 @@ +/********************************************************************** + * sine.h + * + * Created on: Dec 24, 2016 + * Author: tstern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + + +#ifndef SINE_H_ +#define SINE_H_ + +#include "board.h" + +#define SINE_STEPS (1024L) + +#define SINE_MAX ((int32_t)(32768L)) + + +int16_t sine(uint16_t angle); +int16_t cosine(uint16_t angle); + + +#endif /* SINE_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_controller.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_controller.cpp new file mode 100644 index 0000000..a88774f --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_controller.cpp @@ -0,0 +1,1951 @@ +/********************************************************************** + * Author: tstern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "stepper_controller.h" + +#include "nonvolatile.h" //for programmable parameters +#include +#include +#include "steppin.h" + +#pragma GCC push_options +#pragma GCC optimize ("-Ofast") + +#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY); + +volatile bool TC5_ISR_Enabled=false; + +void setupTCInterrupts() { + + // Enable GCLK for TC4 and TC5 (timer counter input clock) + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)); + while (GCLK->STATUS.bit.SYNCBUSY); + + TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; // Disable TCx + WAIT_TC16_REGS_SYNC(TC5) // wait for sync + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16; // Set Timer counter Mode to 16 bits + WAIT_TC16_REGS_SYNC(TC5) + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ; // Set TC as normal Normal Frq + WAIT_TC16_REGS_SYNC(TC5) + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1; // Set perscaler + WAIT_TC16_REGS_SYNC(TC5) + + + TC5->COUNT16.CC[0].reg = F_CPU/NZS_CONTROL_LOOP_HZ; + WAIT_TC16_REGS_SYNC(TC5) + + + TC5->COUNT16.INTENSET.reg = 0; // disable all interrupts + TC5->COUNT16.INTENSET.bit.OVF = 1; // enable overfollow + // TC5->COUNT16.INTENSET.bit.MC0 = 1; // enable compare match to CC0 + + + NVIC_SetPriority(TC5_IRQn, 2); + + + // Enable InterruptVector + NVIC_EnableIRQ(TC5_IRQn); + + + // Enable TC + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; + WAIT_TC16_REGS_SYNC(TC5) + +} + +static void enableTCInterrupts() { + + TC5_ISR_Enabled=true; + NVIC_EnableIRQ(TC5_IRQn); + TC5->COUNT16.INTENSET.bit.OVF = 1; + // TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; //Enable TC5 + // WAIT_TC16_REGS_SYNC(TC5) //wait for sync +} + +static void disableTCInterrupts() { + + TC5_ISR_Enabled=false; + //NVIC_DisableIRQ(TC5_IRQn); + TC5->COUNT16.INTENCLR.bit.OVF = 1; +} + +static bool enterCriticalSection() +{ + bool state=TC5_ISR_Enabled; + disableTCInterrupts(); + return state; +} + +static void exitCriticalSection(bool prevState) +{ + if (prevState) + { + enableTCInterrupts(); + } //else do nothing +} + + +void StepperCtrl::updateParamsFromNVM(void) +{ + bool state=enterCriticalSection(); + + pPID.Kd=NVM->pPID.Kd*CTRL_PID_SCALING; + pPID.Ki=NVM->pPID.Ki*CTRL_PID_SCALING; + pPID.Kp=NVM->pPID.Kp*CTRL_PID_SCALING; + + vPID.Kd=NVM->vPID.Kd*CTRL_PID_SCALING; + vPID.Ki=NVM->vPID.Ki*CTRL_PID_SCALING; + vPID.Kp=NVM->vPID.Kp*CTRL_PID_SCALING; + + sPID.Kd=NVM->sPID.Kd*CTRL_PID_SCALING; + sPID.Ki=NVM->sPID.Ki*CTRL_PID_SCALING; + sPID.Kp=NVM->sPID.Kp*CTRL_PID_SCALING; + + if (NVM->SystemParams.parametersVaild) + { + memcpy((void *)&systemParams, (void *)&NVM->SystemParams, sizeof(systemParams)); + LOG("Home pin %d",systemParams.homePin); + + }else + { + ERROR("This should never happen but just in case"); + systemParams.microsteps=16; + #if defined(CTRL_POS_PID_AS_DEFAULT) + systemParams.controllerMode=CTRL_POS_PID; + #else + systemParams.controllerMode=CTRL_SIMPLE; + #endif + systemParams.dirPinRotation=CW_ROTATION; //default to clockwise rotation when dir is high + systemParams.errorLimit=(int32_t)ANGLE_FROM_DEGREES(1.8); + systemParams.errorPinMode=ERROR_PIN_MODE_ENABLE; //default to enable pin + systemParams.errorLogic=false; + systemParams.homeAngleDelay=ANGLE_FROM_DEGREES(10); + systemParams.homePin=-1; //no homing pin configured + } + + //default the error pin to input, if it is an error pin the + // handler for this will change the pin to be an output. + // for bidirection error it has to handle input/output it's self as well. + // This is not the cleanest way to handle this... + // TODO implement this cleaner? + pinMode(PIN_ERROR, INPUT_PULLUP); //we have input pin + + if (NVM->motorParams.parametersVaild) + { + memcpy((void *)&motorParams, (void *)&NVM->motorParams, sizeof(motorParams)); + } else + { + //MotorParams_t Params; + motorParams.fullStepsPerRotation=200; + motorParams.currentHoldMa=500; + motorParams.currentMa=800; + motorParams.homeHoldMa=200; + motorParams.homeMa=800; + motorParams.motorWiring=true; + //memcpy((void *)&Params, (void *)&motorParams, sizeof(motorParams)); + //nvmWriteMotorParms(Params); + } + + stepperDriver.setRotationDirection(motorParams.motorWiring); + + exitCriticalSection(state); +} + + +void StepperCtrl::motorReset(void) +{ + //when we reset the motor we want to also sync the motor + // phase. Therefore we move forward a few full steps then back + // to sync motor phasing, leaving the motor at "phase 0" + bool state=enterCriticalSection(); + + // stepperDriver.move(0,motorParams.currentMa); + // delay(100); + // stepperDriver.move(A4954_NUM_MICROSTEPS,motorParams.currentMa); + // delay(100); + // stepperDriver.move(A4954_NUM_MICROSTEPS*2,motorParams.currentMa); + // delay(100); + // stepperDriver.move(A4954_NUM_MICROSTEPS*3,motorParams.currentMa); + // delay(100); + // stepperDriver.move(A4954_NUM_MICROSTEPS*2,motorParams.currentMa); + // delay(100); + // stepperDriver.move(A4954_NUM_MICROSTEPS,motorParams.currentMa); + // delay(100); + stepperDriver.move(0,motorParams.currentMa); + delay(1000); + + setLocationFromEncoder(); //measure new starting point + exitCriticalSection(state); +} + +void StepperCtrl::setLocationFromEncoder(void) +{ + numSteps=0; + currentLocation=0; + + if (calTable.calValid()) + { + int32_t n,x; + int32_t calIndex; + Angle a; + + //set our angles based on previous cal data + + x=sampleMeanEncoder(200); + a=calTable.fastReverseLookup(x); + + //our cal table starts at angle zero, so lets set starting based on this and stepsize + LOG("start angle %d, encoder %d", (uint16_t)a,x); + + // we were rounding to nearest full step, but this should not be needed TBS 10/12/2017 + // //TODO we need to handle 0.9 degree motor + // if (CALIBRATION_TABLE_SIZE == motorParams.fullStepsPerRotation) + // { + // n=(int32_t)ANGLE_STEPS/CALIBRATION_TABLE_SIZE; + // + // calIndex=((int32_t)((uint16_t)a+n/2)*CALIBRATION_TABLE_SIZE)/ANGLE_STEPS; //find calibration index + // if (calIndex>CALIBRATION_TABLE_SIZE) + // { + // calIndex-=CALIBRATION_TABLE_SIZE; + // } + // a=(uint16_t)((calIndex*ANGLE_STEPS)/CALIBRATION_TABLE_SIZE); + // } + + + x=(int32_t)((((float)(uint16_t)a)*360.0/(float)ANGLE_STEPS)*1000); + LOG("start angle after rounding %d %d.%03d", (uint16_t)a,x/1000,x%1000); + + //we need to set our numSteps + numSteps=DIVIDE_WITH_ROUND( ((int32_t)a *motorParams.fullStepsPerRotation*systemParams.microsteps),ANGLE_STEPS); + currentLocation=(uint16_t)a; + } + zeroAngleOffset=getCurrentLocation(); //zero the angle shown on LCD +} + +void StepperCtrl::acceptPositionAndStealthSwitchMode(feedbackCtrl_t m) +{ + bool state=enterCriticalSection(); + currentLocationIsDesiredLocation(); + systemParams.controllerMode=m; + exitCriticalSection(state); +} + +void StepperCtrl::stealthSwitchMode(feedbackCtrl_t m) +{ + bool state=enterCriticalSection(); + systemParams.controllerMode=m; + exitCriticalSection(state); +} + +int64_t StepperCtrl::getZeroAngleOffset(void) +{ + int64_t x; + bool state=enterCriticalSection(); + + x=zeroAngleOffset; + + exitCriticalSection(state); + return x; +} + +void StepperCtrl::setAngle(int64_t angle) +{ + bool state=enterCriticalSection(); + + zeroAngleOffset=getCurrentLocation()-angle; + + exitCriticalSection(state); +} + +void StepperCtrl::setZero(void) +{ + //we want to set the starting angle to zero. + bool state=enterCriticalSection(); + + zeroAngleOffset=getCurrentLocation(); + + exitCriticalSection(state); +} + +void StepperCtrl::encoderDiagnostics(char *ptrStr) +{ + bool state=TC5_ISR_Enabled; + disableTCInterrupts(); + + encoder.diagnostics(ptrStr); + + if (state) enableTCInterrupts(); +} + + +//TODO This function does two things, set rotation direction +// and measures step size, it should be two functions. +//return is anlge in degreesx100 ie 360.0 is returned as 36000 +float StepperCtrl::measureStepSize(void) +{ + int32_t angle1,angle2,x,i; + bool feedback=enableFeedback; + int32_t microsteps=systemParams.microsteps; + + systemParams.microsteps=1; + enableFeedback=false; + motorParams.motorWiring=true; //assume we are forward wiring to start with + stepperDriver.setRotationDirection(motorParams.motorWiring); + ///////////////////////////////////////// + //// Measure the full step size ///// + /// Note we assume machine can take one step without issue/// + + LOG("reset motor"); + motorReset(); //this puts stepper motor at stepAngle of zero + + LOG("sample encoder"); + + angle1=sampleMeanEncoder(200); + + LOG("move"); + stepperDriver.move(A4954_NUM_MICROSTEPS/2,motorParams.currentMa); //move one half step 'forward' + delay(100); + stepperDriver.move(A4954_NUM_MICROSTEPS,motorParams.currentMa); //move one half step 'forward' + delay(500); + LOG("sample encoder"); + angle2=sampleMeanEncoder(200); + + LOG("Angles %d %d",angle1,angle2); + if ((abs(angle2-angle1))>(ANGLE_STEPS/2)) + { + //we crossed the wrap around + if (angle1>angle2) + { + angle1=angle1+(int32_t)ANGLE_STEPS; + }else + { + angle2=angle2+(int32_t)ANGLE_STEPS; + } + } + LOG("Angles %d %d",angle1,angle2); + + //when we are increase the steps in the stepperDriver.move() command + // we want the encoder increasing. This ensures motor is moving clock wise + // when encoder is increasing. + // if (angle2>angle1) + // { + // motorParams.motorWiring=true; + // stepperDriver.setRotationDirection(true); + // LOG("Forward rotating"); + // }else + // { + // //the motor is wired backwards so correct in stepperDriver + // motorParams.motorWiring=false; + // stepperDriver.setRotationDirection(false); + // LOG("Reverse rotating"); + // } + x=((int64_t)(angle2-angle1)*36000)/(int32_t)ANGLE_STEPS; + // if x is ~180 we have a 1.8 degree step motor, if it is ~90 we have 0.9 degree step + LOG("%angle delta %d %d (%d %d)",x,abs(angle2-angle1),angle1,angle2 ); + + //move back + stepperDriver.move(-A4954_NUM_MICROSTEPS/2,motorParams.currentMa); //move one half step 'forward' + delay(100); + stepperDriver.move(-A4954_NUM_MICROSTEPS,motorParams.currentMa); //move one half step 'forward' + + systemParams.microsteps=microsteps; + enableFeedback=feedback; + + return ((float)x)/100.0; +} + + +int32_t StepperCtrl::measureError(void) +{ + //LOG("current %d desired %d %d",(int32_t) currentLocation, (int32_t)getDesiredLocation(), numSteps); + + return ((int32_t)currentLocation-(int32_t)getDesiredLocation()); +} + +/* +bool StepperCtrl::changeMicrostep(uint16_t microSteps) +{ + bool state=TC5_ISR_Enabled; + disableTCInterrupts(); + systemParams.microsteps=microSteps; + motorReset(); + if (state) enableTCInterrupts(); + return true; +} + */ +Angle StepperCtrl::maxCalibrationError(void) +{ + //Angle startingAngle; + bool done=false; + int32_t mean; + int32_t maxError=0, j; + int16_t dist; + uint16_t angle=0; + bool feedback=enableFeedback; + uint16_t microSteps=systemParams.microsteps; + int32_t steps; + bool state=TC5_ISR_Enabled; + disableTCInterrupts(); + + + if (false == calTable.calValid()) + { + return ANGLE_MAX; + } + + enableFeedback=false; + j=0; + LOG("Running calibration test"); + + systemParams.microsteps=1; + motorReset(); + steps=0; + + while(!done) + { + Angle cal; + Angle act, desiredAngle; + + //todo we should measure mean and wait until stable. + delay(200); + mean=sampleMeanEncoder(200); + desiredAngle=(uint16_t)(getDesiredLocation() & 0x0FFFFLL); + + cal=calTable.getCal(desiredAngle); + dist=Angle(mean)-cal; + act=calTable.fastReverseLookup(cal); + + LOG("actual %d, cal %d",mean,(uint16_t)cal); + LOG("desired %d",(uint16_t)desiredAngle); + LOG("numSteps %d", numSteps); + + LOG("cal error for step %d is %d",j,dist); + LOG("mean %d, cal %d",mean, (uint16_t)cal); + + updateStep(0,1); + + // move one half step at a time, a full step move could cause a move backwards depending on how current ramps down + steps+=A4954_NUM_MICROSTEPS/2; + stepperDriver.move(steps,motorParams.currentMa); + + delay(50); + steps+=A4954_NUM_MICROSTEPS/2; + stepperDriver.move(steps,motorParams.currentMa); + + + if (400==motorParams.fullStepsPerRotation) + { + delay(100); + updateStep(0,1); + // move one half step at a time, a full step move could cause a move backwards depending on how current ramps down + steps+=A4954_NUM_MICROSTEPS/2; + stepperDriver.move(steps,motorParams.currentMa); + + delay(100); + steps+=A4954_NUM_MICROSTEPS/2; + stepperDriver.move(steps,motorParams.currentMa); + } + //delay(400); + + if (abs(dist)>maxError) + { + maxError=abs(dist); + } + + j++; + if (j>=(1*CALIBRATION_TABLE_SIZE+3)) + { + done=true; + } + + + } + systemParams.microsteps=microSteps; + motorReset(); + enableFeedback=feedback; + if (state) enableTCInterrupts(); + LOG("max error is %d cnts", maxError); + return Angle((uint16_t)maxError); +} + + +//The encoder needs to be calibrated to the motor. +// we will assume full step detents are correct, +// ex 1.8 degree motor will have 200 steps for 360 degrees. +// We also need to calibrate the phasing of the motor +// to the A4954. This requires that the A4954 "step angle" of +// zero is the first entry in the calibration table. +bool StepperCtrl::calibrateEncoder(void) +{ + int32_t x,i,j; + uint32_t angle=0; + int32_t steps; + bool done=false; + + int32_t mean; + uint16_t microSteps=systemParams.microsteps; + bool feedback=enableFeedback; + bool state=TC5_ISR_Enabled; + + disableTCInterrupts(); + + enableFeedback=false; + systemParams.microsteps=1; + LOG("reset motor"); + motorReset(); + LOG("Starting calibration"); + delay(200); + steps=0; + j=0; + while(!done) + { + int ii,N; + Angle cal,desiredAngle; + desiredAngle=(uint16_t)(getDesiredLocation() & 0x0FFFFLL); + cal=calTable.getCal(desiredAngle); + delay(200); + mean=sampleMeanEncoder(200); + + LOG("Previous cal distance %d, %d, mean %d, cal %d",j, cal-Angle((uint16_t)mean), mean, (uint16_t)cal); + + calTable.updateTableValue(j,mean); + + updateStep(0,1); + + N=2; + // move one half step at a time, a full step move could cause a move backwards depending on how current ramps down + for (ii=0; ii=CALIBRATION_TABLE_SIZE) + { + done=true; + } + + + } + //calTable.printCalTable(); + //calTable.smoothTable(); + //calTable.printCalTable(); + calTable.saveToFlash(); //saves the calibration to flash + calTable.printCalTable(); + + systemParams.microsteps=microSteps; + motorReset(); + enableFeedback=feedback; + if (state) enableTCInterrupts(); + return done; +} + + + + + +stepCtrlError_t StepperCtrl::begin(void) +{ + int i; + float x; + + + enableFeedback=false; + velocity=0; + currentLocation=0; + numSteps=0; + + //we have to update from NVM before moving motor + updateParamsFromNVM(); //update the local cache from the NVM + + LOG("start up encoder"); + if (false == encoder.begin(PIN_AS5047D_CS)) + { + return STEPCTRL_NO_ENCODER; + } + + LOG("cal table init"); + calTable.init(); + + startUpEncoder=(uint16_t)getEncoderAngle(); + WARNING("start up encoder %d",startUpEncoder); + + LOG("start stepper driver"); + stepperDriver.begin(); + +#ifdef NEMA17_SMART_STEPPER_3_21_2017 + if (NVM->motorParams.parametersVaild) + { + //lets read the motor voltage + if (GetMotorVoltage()<5) + { + //if we have less than 5 volts the motor is not powered + uint32_t x; + x=(uint32_t)(GetMotorVoltage()*1000.0); + ERROR("Motor voltage is %" PRId32 "mV",x); //default printf does not support floating point numbers + ERROR("Motor may not have power"); + return STEPCTRL_NO_POWER; + } + bool state=enterCriticalSection(); + setLocationFromEncoder(); //measure new starting point + exitCriticalSection(state); + + }else + { + LOG("measuring step size"); + x=measureStepSize(); + if (abs(x)<0.5) + { + ERROR("Motor may not have power"); + return STEPCTRL_NO_POWER; + } + } + +#else + LOG("measuring step size"); + x=measureStepSize(); + if (abs(x)<0.5) + { + ERROR("Motor may not have power"); + return STEPCTRL_NO_POWER; + } +#endif + + + LOG("Checking the motor parameters"); + //todo we might want to move this up a level to the NZS + // especially since it has default values + if (false == NVM->motorParams.parametersVaild) + { + MotorParams_t params; + WARNING("NVM motor parameters are not set, we will update"); + + //power could have just been applied and step size read wrong + // if we are more than 200 steps/rotation which is most common + // lets read again just to be sure. + if (abs(x)<1.5) + { + //run step test a second time to be sure + x=measureStepSize(); + } + + if (x>0) + { + motorParams.motorWiring=true; + } else + { + motorParams.motorWiring=false; + } + if (abs(x)<=1.2) + { + motorParams.fullStepsPerRotation=400; + }else + { + motorParams.fullStepsPerRotation=200; + } + + memcpy((void *)¶ms, (void *)&motorParams,sizeof(motorParams)); + nvmWriteMotorParms(params); + } + + LOG("Motor params are now good"); + LOG("fullSteps %d", motorParams.fullStepsPerRotation); + LOG("motorWiring %d", motorParams.motorWiring); + LOG("currentMa %d", motorParams.currentMa); + LOG("holdCurrentMa %d", motorParams.currentHoldMa); + LOG("homeMa %d", motorParams.homeMa); + LOG("homeHoldMa %d", motorParams.homeHoldMa); + + + updateParamsFromNVM(); //update the local cache from the NVM + + + if (false == calTable.calValid()) + { + return STEPCTRL_NO_CAL; + } + + + enableFeedback=true; + setupTCInterrupts(); + enableTCInterrupts(); + return STEPCTRL_NO_ERROR; + +} + +Angle StepperCtrl::sampleAngle(void) +{ + uint16_t angle; + int32_t x,y; + +#ifdef NZS_AS5047_PIPELINE + //read encoder twice such that we get the latest sample as the pipeline is always once sample behind + + + y=encoder.readEncoderAnglePipeLineRead(); //convert the 14 bit encoder value to a 16 bit number + x=encoder.readEncoderAnglePipeLineRead(); + + + angle=((uint32_t)(x)*4); //convert the 14 bit encoder value to a 16 bit number +#else + angle=((uint32_t)encoder.readEncoderAngle())<<2; //convert the 14 bit encoder value to a 16 bit number +#endif + return Angle(angle); +} + +//when sampling the mean of encoder if we are on roll over +// edge we can have an issue so we have this function +// to do the mean correctly +Angle StepperCtrl::sampleMeanEncoder(int32_t numSamples) +{ + + int32_t i,last,x=0; + int64_t mean=0; + int32_t min,max; + + mean=0; + for (i=0; i<(numSamples); i++) + { + int32_t d; + last=x; + x=(((int32_t)encoder.readEncoderAngle())*4); + if (encoder.getError()) + { +#ifndef MECHADUINO_HARDWARE + SerialUSB.println("AS5047 Error"); +#else + Serial5.print("AS5047 Error"); +#endif + delay(1000); + return 0; + } + if(i==0) + { + last=x; + min=x; + max=x; + } + //LOG("i %d,min %d, max %d, last %d, x %d", i, min, max, last, x); + if (abs(last-x)>65536/2) + { + if (last>x) + { + x=x+65536; + } else + { + x=x-65536; + } + } + + + if (x>max) + { + max=x; + } + if (xn) + { + ret-=n; + } + while(ret<-n) + { + ret+=n; + } + n=(int32_t)(ret); + LOG("s is %d %d",n,steps); + stepperDriver.move(n,motorParams.currentMa); + } + + +} + + + +int64_t StepperCtrl::getDesiredLocation(void) +{ + int64_t ret; + int32_t n; + bool state=TC5_ISR_Enabled; + disableTCInterrupts(); + n=motorParams.fullStepsPerRotation * systemParams.microsteps; + ret=((int64_t)numSteps * (int64_t)ANGLE_STEPS+(n/2))/n ; + if (state) enableTCInterrupts(); + return ret; +} + + +//int32_t StepperCtrl::getSteps(void) +//{ +// int32_t ret; +// bool state=enterCriticalSection(); +// ret=numSteps; +// exitCriticalSection(state); +// return ret; +//} + +void StepperCtrl::moveToAbsAngle(int32_t a) +{ + + int64_t ret; + int32_t n; + + + n=motorParams.fullStepsPerRotation * systemParams.microsteps; + + ret=(((int64_t)a+zeroAngleOffset)*n+ANGLE_STEPS/2)/(int32_t)ANGLE_STEPS; + bool state=enterCriticalSection(); + numSteps=ret; + exitCriticalSection(state); +} + +void StepperCtrl::moveToAngle(int32_t a, uint32_t ma) +{ + //we need to convert 'Angle' to A4954 steps + a=a % ANGLE_STEPS; //we only interested in the current angle + + + a=DIVIDE_WITH_ROUND( (a*motorParams.fullStepsPerRotation*A4954_NUM_MICROSTEPS), ANGLE_STEPS); + + //LOG("move %d %d",a,ma); + stepperDriver.move(a,ma); + +} + +Angle StepperCtrl::getEncoderAngle(void) +{ + Angle a; + bool state=enterCriticalSection(); + a=calTable.fastReverseLookup(sampleAngle()); + exitCriticalSection(state); + return a; +} + +int64_t StepperCtrl::getCurrentLocation(void) +{ + Angle a; + int32_t x; + bool state=TC5_ISR_Enabled; + disableTCInterrupts(); + a=calTable.fastReverseLookup(sampleAngle()); + x=(int32_t)a - (int32_t)((currentLocation) & ANGLE_MAX); + + if (x>((int32_t)ANGLE_STEPS/2)) + { + currentLocation -= ANGLE_STEPS; + } + if (x<-((int32_t)ANGLE_STEPS/2)) + { + currentLocation += ANGLE_STEPS; + } + currentLocation=(currentLocation & 0xFFFFFFFFFFFF0000UL) | (uint16_t)a; + if (state) enableTCInterrupts(); + return currentLocation; + +} + + + +int64_t StepperCtrl::getCurrentAngle(void) +{ + int64_t x; + x=getCurrentLocation()-zeroAngleOffset; + return x; +} + + +int64_t StepperCtrl::getDesiredAngle(void) +{ + int64_t x; + x=getDesiredLocation()-zeroAngleOffset; + return x; +} + +void StepperCtrl::setVelocity(int64_t vel) +{ + bool state=enterCriticalSection(); + + velocity=vel; + exitCriticalSection(state); +} + +void StepperCtrl::setTorque(int8_t tor) +{ + bool state=enterCriticalSection(); + + torque=tor; + exitCriticalSection(state); +} + +int8_t StepperCtrl::getTorque(void) +{ + int8_t tor; + bool state=enterCriticalSection(); + + tor=torque; + exitCriticalSection(state); + return tor; +} + +int64_t StepperCtrl::getVelocity(void) +{ + int64_t vel; + bool state=enterCriticalSection(); + + vel=velocity; + exitCriticalSection(state); + return vel; +} + +bool StepperCtrl::torqueLoop(int64_t currentLoc, Control_t *ptrCtrl) +{ + int32_t U, ma; + int64_t u, y; + + int32_t fullStep=ANGLE_STEPS/motorParams.fullStepsPerRotation; + + y=currentLoc; + ma=motorParams.currentMa; + u=torque*ma/128; // Make ma the maximum torque at 128 + // If dir pin changes meaning then torque also changes direction + if (CW_ROTATION == systemParams.dirPinRotation) + { + u=-u; + } + U=abs(u); + if (U>ma) + U=ma; + if (u>0) + y=y+fullStep; + else + y=y-fullStep; + ptrCtrl->ma=U; + ptrCtrl->angle=(int32_t)y; + moveToAngle(y,U); +} + +void StepperCtrl::PrintData(void) +{ + char s[128]; + bool state=enterCriticalSection(); + sprintf(s, "%u,%u,%u", (uint32_t)numSteps,(uint32_t)getDesiredAngle(),(uint32_t)getCurrentAngle()); +#ifndef MECHADUINO_HARDWARE + SerialUSB.println(s); +#endif + exitCriticalSection(state); +} +//this is the velocity PID feedback loop +bool StepperCtrl::vpidFeedback(int64_t desiredLoc, int64_t currentLoc, Control_t *ptrCtrl) +{ + int32_t fullStep=ANGLE_STEPS/motorParams.fullStepsPerRotation; + static int64_t lastY=getCurrentLocation(); + static int32_t lastError=0; + static int64_t Iterm=0; + int64_t y,z; + int64_t v,dy; + int64_t u; + + //get the current location + y =currentLoc; + + v=y-lastY; + + //add in phase prediction + y=y+calculatePhasePrediction(currentLoc); + z=y; + + lastY=y; + + v=v*NZS_CONTROL_LOOP_HZ; + + + if (enableFeedback) //if ((micros()-lastCall)>(updateRate/10)) + { + int64_t error,U; + error = velocity-v; + + Iterm += (vPID.Ki * error); + if (Iterm>(16*4096*CTRL_PID_SCALING *(int64_t)motorParams.currentMa)) + { + Iterm=(16*4096*CTRL_PID_SCALING *(int64_t)motorParams.currentMa); + } + if (Iterm<-(16*4096*CTRL_PID_SCALING *(int64_t)motorParams.currentMa)) + { + Iterm=-(16*4096*CTRL_PID_SCALING*(int64_t)motorParams.currentMa); + } + + u=((vPID.Kp * error) + Iterm - (vPID.Kd *(lastError-error))); + U=abs(u)/CTRL_PID_SCALING/1024; //scale the error to make PID params close to 1.0;//scale the error to make PID params close to 1.0 by dividing by 1024 + + if (U>motorParams.currentMa) + { + U=motorParams.currentMa; + } + + //when error is positive we need to move reverse direction + if (u>0) + { + z=z+(fullStep); + }else + { + z=z-(fullStep); + + } + + ptrCtrl->ma=U; + ptrCtrl->angle=(int32_t)z; + moveToAngle(z,U); + loopError=error; + lastError=error; + } else + { + lastError=0; + Iterm=0; + } + + if (abs(lastError)>(systemParams.errorLimit)) + { + return 1; + } + return 0; +} + + +//Since we are doing fixed point math our +// threshold needs to be large. +// We need a large threshold when we have fast update +// rate as well. But for most part it is random +bool StepperCtrl::pidFeedback(int64_t desiredLoc, int64_t currentLoc, Control_t *ptrCtrl) +{ + static int count=0; + + static int32_t maxError=0; + static int32_t lastError=0; + static int32_t Iterm=0; + int32_t ma; + int64_t y; + + int32_t fullStep=ANGLE_STEPS/motorParams.fullStepsPerRotation; + int32_t dy; + + y=currentLoc; + + //add in phase prediction + y=y+calculatePhasePrediction(currentLoc); + + if (enableFeedback) //if ((micros()-lastCall)>(updateRate/10)) + { + int64_t error,u; + int32_t U,x; + + //error is in units of degrees when 360 degrees == 65536 + error=(desiredLoc-y); //error is currentPos-desiredPos + + Iterm+=(pPID.Ki * error); + + if (systemParams.homePin>0 && digitalRead(systemParams.homePin)==0) + { + ma=motorParams.homeMa; + } else + { + ma=motorParams.currentMa; + } + + //Over the long term we do not want error + // to be much more than our threshold + if (Iterm> (ma*CTRL_PID_SCALING) ) + { + Iterm=(ma*CTRL_PID_SCALING) ; + } + if (Iterm<-(ma*CTRL_PID_SCALING) ) + { + Iterm=-(ma*CTRL_PID_SCALING) ; + } + + //u=((pPID.Kp * error) + Iterm - (pPID.Kd *(lastError-error))); + if(abs(error) > 90304) // 540 degrees + { + u=(int64_t)((float)ma*(float)CTRL_PID_SCALING*90304.0/(float)error); + } + else + { + u=((pPID.Kp * error) + Iterm - (pPID.Kd *(lastError-error))); + } + + U=abs(u)/CTRL_PID_SCALING; + if (U>ma) + { + U=ma; + } + + + //when error is positive we need to move reverse direction + if (u>0) + { + y=y+fullStep; + }else + { + y=y-fullStep; + + } + + ptrCtrl->ma=U; + ptrCtrl->angle=(int32_t)y; + moveToAngle(y,U); + loopError=error; + lastError=error; + + }else + { + lastError=0; + Iterm=0; + } + + if (abs(lastError)>(systemParams.errorLimit)) + { + return 1; + } + return 0; +} + + + +// the phase prediction tries to predict error from sensor based +// on current location and previous location. +// TODO our error can help in the phase prediction. +// if the error +int64_t StepperCtrl::calculatePhasePrediction(int64_t currentLoc) +{ + static int64_t lastLoc=0; + static int32_t mean=0; + int32_t dx,x; + +#ifndef ENABLE_PHASE_PREDICTION + return 0; +#endif + + //what was our change in the location + dx=currentLoc-lastLoc; //max value is typically less than 327(1.8 degrees) or 163(0.9 degree) + + //if the motor direction changes, zero phase prediction + if (SIGN(dx) != SIGN(mean)) + { + //last thing we want is phase prediction during direction change. + mean=0; + } else + { + if (abs(dx)>abs(mean)) + { + //increase mean really slowly, 2048 ~ 1/3 second with 6khz processing loop + // in fixed point since the dx is so small we need to scale it up to average + // dx has be be greater than 8 to change the mean... + // this limits the acceleration of motor above max processing speed (6k*1.8)=1800RPM + // however I doubt the motor can accelerate that fast with any load... + // The average helps prevent external impulse error from causing prediction to cause issues. + mean=DIVIDE_WITH_ROUND(2047*mean + dx*128, 2048); + }else + { + //decrease fast + //do not add more phase prediction than the difference in last two samples. + mean=dx*128; + } + } + lastLoc=currentLoc; + + x= mean/128; //scale back to normal + return x; +} + + +bool StepperCtrl::determineError(int64_t currentLoc,int64_t error) +{ + static int64_t lastLocation=0; + static int64_t lastError=0; + static int64_t lastVelocity=0; + + int64_t velocity; + + //since this is called on periodic timer the velocity + // is propotional to the change in location + // one rotation per second is velocity of 10, assumming 6khz update rate + // one rotation per minute is 10/60 velocity units + // since this is less than 1 we will scale the velo + velocity=(currentLoc-lastLocation); + + if (velocity>0 && lastVelocity>0) + { + + } + + + lastVelocity=velocity; + lastError=error; + lastLocation=currentLoc; +} + +//this was written to do the PID loop not modeling a DC servo +// but rather using features of stepper motor. +bool StepperCtrl::simpleFeedback(int64_t desiredLoc, int64_t currentLoc, Control_t *ptrCtrl) +{ + static uint32_t t0=0; + static uint32_t calls=0; + bool ret=false; + + static int32_t maxError=0; + static int32_t lastError=0; + static int32_t i=0; + static int32_t iTerm=0; + //static int64_t lastY=getCurrentLocation(); + static int32_t velocity=0; + static int32_t errorCount=0; + + static bool lastProbeState=false; + static int64_t probeStartAngle=0; + static int32_t maxMa=0; + + + static int64_t filteredError=0; + static int32_t probeCount=0; + + int32_t fullStep=ANGLE_STEPS/motorParams.fullStepsPerRotation; + + int32_t ma=0; + + int64_t y; + + + + //estimate our current location based on the encoder + y=currentLoc; + + //add in phase prediction + y=y+calculatePhasePrediction(currentLoc); + + + //we can limit the velocity by controlling the amount we move per call to this function + // this only works for velocity greater than 100rpm + /* if (velocity!=0) + { + fullStep=velocity/NZS_CONTROL_LOOP_HZ; + } + if (fullStep==0) + { + fullStep=1; //this RPM of (1*NZS_CONTROL_LOOP_HZ)/60 ie at 6Khz it is 100RPM + } + */ + if (enableFeedback) + { + int64_t error; + int32_t u; + + int32_t x; + int32_t kp; + + //error is in units of degrees when 360 degrees == 65536 + error=(desiredLoc-y);//measureError(); //error is currentPos-desiredPos + + + //data[i]=(int16_t)error; + //i++; + if (i>=N_DATA) + { + i=0; + } + + kp=sPID.Kp; + if (1)//(abs(error)<(fullStep)) + { + iTerm+=(sPID.Ki*error); + x=iTerm/CTRL_PID_SCALING; + }else + { + kp=(CTRL_PID_SCALING*9)/10; + x=0; + iTerm=0; + } + + if (x>fullStep) + { + x=fullStep; + iTerm=fullStep; + } + if (x<-fullStep) + { + x=-fullStep; + iTerm=-fullStep; + } + + + //u=(kp * error)/CTRL_PID_SCALING+x+(sPID.Kd *(error-lastError))/CTRL_PID_SCALING; + + // Lower effort if we're very far off + if(abs(error) > 90304) // 540 degrees + { + u=(int64_t)((float)fullStep*90304.0/(float)error); + } + else + { + u=(kp * error)/CTRL_PID_SCALING+x+(sPID.Kd *(error-lastError))/CTRL_PID_SCALING; + } + + //limit error to full step + if (u>fullStep) + { + u=fullStep; + } + if (u<-fullStep) + { + u=-fullStep; + } + + ma=(abs(u)*(motorParams.currentMa-motorParams.currentHoldMa))/ fullStep + motorParams.currentHoldMa; + if (ma>motorParams.currentMa) + { + ma=motorParams.currentMa; + } + //maxMa=motorParams.currentMa; + + if (systemParams.homePin>=0) + { + + if (digitalRead(systemParams.homePin)==0) + { + if (lastProbeState==false) + { + //record our current angle for homing + probeStartAngle=desiredLoc; + probeCount=0; + maxMa=0; + } + lastProbeState=true; + probeCount++; + //we will lower current after whe have moved some amount + + if (probeCount > NZS_CONTROL_LOOP_HZ && probeCount <(2* NZS_CONTROL_LOOP_HZ)) + { + maxMa+=ma; + if (abs(error)>maxError) + { + maxError=abs(error); + } + + } + if (probeCount>(2*NZS_CONTROL_LOOP_HZ)) + { + // ma=(abs(u)*(maxMa))/ fullStep;// + motorParams.homeHoldMa; + // if (ma>motorParams.homeMa) + // { + // ma=motorParams.homeMa; + // } + + //if (ma>maxMa/NZS_CONTROL_LOOP_HZ) + { + ma=((maxMa/NZS_CONTROL_LOOP_HZ)*9)/10; + } + + } + + } else + { + lastProbeState=false; + } + }else + { + maxError=0; + probeCount=0; + //maxMa=0; + } + + + y=y+u; + ptrCtrl->ma=ma; + ptrCtrl->angle=(int32_t)y; + moveToAngle(y,ma); //35us + + lastError=error; + loopError=error; + //stepperDriver.limitCurrent(99); + } + + //filteredError=(filteredError*15+lastError)/16; + + if (probeCount>(2*NZS_CONTROL_LOOP_HZ)) + { + if (abs(lastError) > maxError ) + { + + errorCount++; + if (errorCount>(10)) + { + return 1; + } + return 0; + } + + } + else + { + if (abs(lastError) > systemParams.errorLimit) + { + + errorCount++; + if (errorCount>(NZS_CONTROL_LOOP_HZ/128)) // error needs to exist for some time period + { + return 1; + } + return 0; + } + } + + if (errorCount>0) + { + errorCount--; + } + + //errorCount=0; + stepperDriver.limitCurrent(99); //reduce noise on low error + return 0; + +} + +void StepperCtrl::currentLocationIsDesiredLocation(){ + bool state=enterCriticalSection(); + moveToAbsAngle(getCurrentAngle()); + exitCriticalSection(state); +} + +void StepperCtrl::enable(bool enable) +{ + bool state=TC5_ISR_Enabled; + disableTCInterrupts(); + bool feedback=enableFeedback; + + stepperDriver.enable(enable); //enable or disable the stepper driver as needed + + + if (enabled==true && enable==false) + { + feedback = false; + } + if (enabled==false && enable==true) //if we are enabling previous disabled motor + { + feedback = true; + setLocationFromEncoder(); + } + + enabled=enable; + enableFeedback=feedback; + if (state) enableTCInterrupts(); +} + +/* +void StepperCtrl::testRinging(void) +{ + uint16_t c; + int32_t steps; + int32_t microSteps=systemParams.microsteps; + bool feedback=enableFeedback; + + enableFeedback=false; + systemParams.microsteps=1; + motorReset(); + for (c=2000; c>10; c=c-10) + { + SerialUSB.print("Current "); + SerialUSB.println(c); + steps+=A4954_NUM_MICROSTEPS; + stepperDriver.move(steps,NVM->SystemParams.currentMa); + currentLimit=false; + measure(); + } + systemParams.microsteps=microSteps; + motorReset(); + enableFeedback=feedback; +} + */ + +//returns -1 if no data, else returns number of data points remaining. +int32_t StepperCtrl::getLocation(Location_t *ptrLoc) +{ + bool state=enterCriticalSection(); + int32_t n; + //check for empty + if (locReadIndx==locWriteIndx) + { + //empty data + exitCriticalSection(state); + return -1; + } + + //else read data + memcpy(ptrLoc,(void *)&locs[locReadIndx], sizeof(Location_t)); + + //update the read index + locReadIndx=(locReadIndx+1)%MAX_NUM_LOCATIONS; + + //calculate number of locations left + n=((locWriteIndx+MAX_NUM_LOCATIONS)-locReadIndx)%MAX_NUM_LOCATIONS; + + + exitCriticalSection(state); + return n; +} + +void StepperCtrl::updateLocTable(int64_t desiredLoc, int64_t currentLoc, Control_t *ptrCtrl) +{ + bool state=enterCriticalSection(); + int32_t next; + + // set the next write location + next=(locWriteIndx+1)%MAX_NUM_LOCATIONS; + + if (next==locReadIndx) + { + //we are full, exit + exitCriticalSection(state); + //RED_LED(true); //turn Red LED on to indciate buffer full + return; + } + + //use ticks for the moment so we can tell if we miss data on the print. + locs[locWriteIndx].microSecs=(int32_t)micros(); + locs[locWriteIndx].desiredLoc=(int32_t)(desiredLoc-zeroAngleOffset); + locs[locWriteIndx].actualLoc=(int32_t)(currentLoc-zeroAngleOffset); + locs[locWriteIndx].angle=(ptrCtrl->angle-zeroAngleOffset); + locs[locWriteIndx].ma=ptrCtrl->ma; + locWriteIndx=next; + + + exitCriticalSection(state); +} + + +bool StepperCtrl::processFeedback(void) +{ + bool ret; + int32_t us,j; + Control_t ctrl; + int64_t desiredLoc; + int64_t currentLoc; + int32_t steps; + static int64_t mean=0;; + + us=micros(); + +#ifdef USE_TC_STEP + static int64_t lastSteps; + int64_t x; + x=getSteps()-lastSteps; + updateSteps(x); + lastSteps+=x; +#endif + +// steps=getSteps(); +// if (steps>0) +// { +// requestStep(1, (uint16_t)steps); +// }else +// { +// requestStep(0, (uint16_t)(-steps)); +// } + + desiredLoc=getDesiredLocation(); + + currentLoc=getCurrentLocation(); + mean=(31*mean+currentLoc+16)/32; + +#ifdef A5995_DRIVER //the A5995 is has more driver noise + if (abs(currentLoc-mean)PIDparams.Kp; + // pKi=NVM->PIDparams.Ki; + // pKd=NVM->PIDparams.Kd; + // threshold=NVM->PIDparams.Threshold; + + //enableTCInterrupts(); + moveToAngle(angle,motorParams.currentMa); + + + //moveToAngle(angle,NVM->SystemParams.currentMa); + /* + //next lets measure our noise on the encoder + noiseMin=(int32_t)ANGLE_MAX; + noiseMax=-(int32_t)ANGLE_MAX; + mean=0; + j=1000000UL/NZS_CONTROL_LOOP_HZ; + prevAngle=sampleAngle(); + for (i=0; i<(NZS_CONTROL_LOOP_HZ/2); i++) + { + Angle a; + a=sampleAngle(); + error=(int32_t)(prevAngle-a); + + if (errornoiseMax) + { + noiseMax=error; + } + mean=mean+(int32_t)a; + delayMicroseconds(j); + + } + mean=mean/i; + while (mean>ANGLE_MAX) + { + mean=mean-ANGLE_STEPS; + } + while (mean<0) + { + mean=mean+ANGLE_STEPS; + } + //mean is the average of the encoder. + */ + + + + stepperDriver.move(0,motorParams.currentMa); + delay(1000); + + //now we need to do the relay control + for (i=0; i<10; i++) + { + startAngle=getCurrentLocation(); + LOG("Start %d", (int32_t)startAngle); + } + thres=startAngle + (int32_t)((ANGLE_STEPS/motorParams.fullStepsPerRotation)*10/9); + LOG("Thres %d, start %d",(int32_t)thres,(int32_t)startAngle); + eMin=(int32_t)ANGLE_MAX; + eMax=-(int32_t)ANGLE_MAX; + int32_t reset=0; + int32_t force=(motorParams.currentMa); + + for (i=0; i<100; i++) + { + int32_t error; + if (reset) + { + motorReset(); + stepperDriver.move(0,motorParams.currentMa); + delay(1000); + startAngle=getCurrentLocation(); + LOG("Start %d", (int32_t)startAngle); + force=force-100; + + eMin=(int32_t)ANGLE_MAX; + eMax=-(int32_t)ANGLE_MAX; + + if (force<100) + { + i=100; + break; + } + LOG("force set to %d",force); + i=0; + } + reset=0; + + stepperDriver.move(A4954_NUM_MICROSTEPS,force); + //moveToAngle(startAngle+(ANGLE_STEPS/motorParams.fullStepsPerRotation),force); + //stepperDriver.move(A4954_NUM_MICROSTEPS,NVM->SystemParams.currentMa); + t0=micros(); + + error=0; + while(error<=((ANGLE_STEPS/motorParams.fullStepsPerRotation)/2+40)) + { + int32_t y; + y=getCurrentLocation(); + error=y-startAngle; + //LOG("Error1 %d",error); + if (erroreMax) + { + eMax=error; + } + if (abs(error)>ANGLE_STEPS/motorParams.fullStepsPerRotation*2) + { + LOG("large Error1 %d, %d, %d",error, y, startAngle); + + reset=1; + break; + } + + } + + stepperDriver.move(0,force); + + //stepperDriver.move(0,NVM->SystemParams.currentMa); + t1=micros(); + + error=(ANGLE_STEPS/motorParams.fullStepsPerRotation); + while(error>=((ANGLE_STEPS/motorParams.fullStepsPerRotation)/2-40)) + { + error=getCurrentLocation()-startAngle; + //LOG("Error2 %d",error); + if (erroreMax) + { + eMax=error; + } + if (abs(error)>ANGLE_STEPS/motorParams.fullStepsPerRotation*2) + { + LOG("large Error2 %d",error); + reset=1; + break; + } + } + + times[i]=t1-t0; + + } + for (i=0; i<100; i++) + { + LOG("Time %d %d",i,times[i]); + } + LOG("errorMin=%d",eMin); + LOG("errorMax=%d",eMax); + + motorReset(); + systemParams.controllerMode=prevCtrl; + systemParams.microsteps=microSteps; + enableFeedback=feedback; + if (state) enableTCInterrupts(); + +} + +//void StepperCtrl::printData(void) +//{ +// bool state=TC5_ISR_Enabled; +// disableTCInterrupts(); +// int32_t i; +// for(i=0; i. + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#ifndef __STEPPER_CONTROLLER_H__ +#define __STEPPER_CONTROLLER_H__ + +#include "syslog.h" +#include "board.h" +#include "as5047d.h" +#include "A1333.h" +#include "calibration.h" +#include "A4954.h" +#include "A5995.h" +#include "nonvolatile.h" +#include "fet_driver.h" //for the NEMA23 10A + + +#define N_DATA (1024) + + +typedef enum { + STEPCTRL_NO_ERROR=0, + STEPCTRL_NO_POWER=1, //no power to motor + STEPCTRL_NO_CAL=2, //calibration not set + STEPCTRL_NO_ENCODER=3, //encoder not working +} stepCtrlError_t; + + +typedef struct { + int32_t Kp; + int32_t Ki; + int32_t Kd; +} PID_t; + + + typedef __attribute__((aligned(4))) struct { + int32_t microSecs; + int32_t desiredLoc; + int32_t actualLoc; + int32_t angle; + int32_t ma; +} Location_t; + + +typedef struct { + int32_t angle; + int32_t ma; +}Control_t; + +#define MAX_NUM_LOCATIONS (64) //maximum number of locations to buffer + + +//this scales the PID parameters from Flash to floating point +// to fixed point int32_t values +#define CTRL_PID_SCALING (1024) + +// Uncommenting this will make motor go into ctrl_pos_pid mode +// at startup and when exiting ctrl_torque mode by setting torque=0 +//#define CTRL_POS_PID_AS_DEFAULT + +class StepperCtrl +{ + private: + volatile bool enableFeedback; //true if we are using PID control algorithm + +#ifdef A1333_ENCODER + A1333 encoder; +#else + AS5047D encoder; +#endif + +#ifdef NEMA_23_10A_HW + FetDriver stepperDriver; +#else +#ifdef A5995_DRIVER + A5995 stepperDriver; +#else + A4954 stepperDriver; +#endif +#endif + uint16_t startUpEncoder; + volatile int32_t ticks=0; + volatile Location_t locs[MAX_NUM_LOCATIONS]; + volatile int32_t locReadIndx=0; + volatile int32_t locWriteIndx=0; + + volatile MotorParams_t motorParams; + volatile SystemParams_t systemParams; + volatile bool enabled; + + + + volatile int32_t loopTimeus; //time to run loop in microseconds + + volatile PID_t sPID; //simple control loop PID parameters + volatile PID_t pPID; //positional current based PID control parameters + volatile PID_t vPID; //velocity PID control parameters + + volatile int64_t numSteps; //this is the number of steps we have taken from our start angle + + volatile int32_t loopError; + + volatile int64_t currentLocation; //estimate of the current location from encoder feedback + // the current location lower 16 bits is angle (0-360 degrees in 65536 steps) while upper + // bits is the number of full rotations. + + //this is used for the velocity PID feedback + // units are in Angles/sec where 1 Angle=360deg/65536 + volatile int64_t velocity; + volatile int8_t torque=0; + + int64_t zeroAngleOffset=0; + + + //volatile int16_t data[N_DATA]; + + //does linear interpolation of the encoder calibration table + int32_t getAngleCalibration(int32_t encoderAngle); + + //updates the currentMeasuredAngle with our best guess where we are + Angle sampleAngle(void); + Angle sampleMeanEncoder(int32_t numSamples); + + float measureStepSize(void); //steps motor and estimates step size + uint32_t measureMaxCalibrationError(void); + void setLocationFromEncoder(void); + + void motorReset(void); + void updateStep(int dir, uint16_t steps); + + bool torqueLoop(int64_t currentLoc, Control_t *ptrCtrl); + bool pidFeedback(int64_t desiredLoc, int64_t currentLoc, Control_t *ptrCtrl); + bool simpleFeedback(int64_t desiredLoc, int64_t currentLoc,Control_t *ptrCtrl); + bool vpidFeedback(int64_t desiredLoc, int64_t currentLoc,Control_t *ptrCtrl); + int64_t getCurrentLocation(void); + int64_t getDesiredLocation(void); + void updateLocTable(int64_t desiredLoc, int64_t currentLoc,Control_t *ptrCtrl); + + int64_t calculatePhasePrediction(int64_t currentLoc); + bool determineError(int64_t currentLoc, int64_t error); + + public: + uint16_t getStartupEncoder(void) {return startUpEncoder;} + int32_t getLocation(Location_t *ptrLoc); + + //int32_t getSteps(void); + Angle getEncoderAngle(void); + + void setAngle(int64_t loc); + + int64_t getZeroAngleOffset(void); + void PrintData(void); + void setTorque(int8_t tor); //set torqu for torque mode + int8_t getTorque(void); + void setVelocity(int64_t vel); //set velocity for vPID mode + int64_t getVelocity(void); + int32_t getLoopError(void) {return loopError;}; //assume atomic read + + bool calibrationValid(void) { return calTable.calValid();} //returns true if calbiration is good + + void updateParamsFromNVM(void); //updates the parameters from NVM + CalibrationTable calTable; + //void printData(void); + + bool calibrateEncoder(void); //do manual calibration of the encoder + Angle maxCalibrationError(void); //measures the maximum calibration error as an angle + + void moveToAbsAngle(int32_t a); + void moveToAngle(int32_t a, uint32_t ma); + + stepCtrlError_t begin(void); //returns false if we can not use motor + + bool processFeedback(void); // does the feedback loop + + feedbackCtrl_t getControlMode(void) { return systemParams.controllerMode;}; + + void updateSteps(int64_t steps); + void requestStep(int dir, uint16_t steps); //requests a step, if feedback controller is off motor does not move + + void feedback(bool enable); + bool getFeedback(void) {return enableFeedback;} + + void encoderDiagnostics(char *ptrStr); + int32_t measureError(void); + + //these two functions are compenstated by the zero offset + int64_t getCurrentAngle(void); + int64_t getDesiredAngle(void); + + void move(int dir, uint16_t steps); //forces motor to move even if feedback controller is turned off. + void currentLocationIsDesiredLocation(); + void stealthSwitchMode(feedbackCtrl_t m); + void acceptPositionAndStealthSwitchMode(feedbackCtrl_t m); + void enable(bool enable); + bool getEnable(void) {return enabled;} + + int32_t getLoopTime(void) { return loopTimeus;} + + void PID_Autotune(void); + void setZero(void); +}; + +#endif //__STEPPER_CONTROLLER_H__ + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.ino b/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.ino new file mode 100644 index 0000000..62794ae --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.ino @@ -0,0 +1,13 @@ +#include "nzs.h" + +NZS nzs; + + +void setup() { + nzs.begin(); +} + + +void loop() { + nzs.loop(); +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.misfittech.samd.nano_zero.bin b/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.misfittech.samd.nano_zero.bin new file mode 100644 index 0000000000000000000000000000000000000000..65bfa29639f5acb43d9e0b44ce13a659ce732537 GIT binary patch literal 119788 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

3YHKQK!S44tH8oW=2;jp?Cq%1LO1VmR8?{& zXF6KcP+qgE)|zU#+Uf{|Ey$WPD{t0KnH=XXY5rU-H>=9Vl~h$$no4Y@5isP;o>N@J z<;}{QHzTHm-8U3Fmbh3 zV0;8Y{ehn1!BU`O5?wlHb`fW_RDkFBTad$TwIMheG(_ffwo-uCbJ2S1Ch^$YtZr4WZ?7G{tqjEmZsnxSL zy>*i%Hz4o1yoLE!^E(S>7CH(y6>+m(o3*s~YVn@gsW*Revt^E8Zu{JndB^4%=KnhX z-djQ!9A2PZcw%AcqMsLSUMyeIu_X4^=Wd;`^u49U%l@`(>GBK9&4zy(DviCy+gALz zqPpaVlJe4TN=r;|nGyJf&qvFgmK{MCP1ttx-8{BpUm;#h^c za(Cs`%4Jn=R7F$a_Xf1UXDtlQV${`~Df+&=z}TkqI$$2)gix+8A= z;`Q6sKfnIM`hX2nHmuli?}o!0zSwYOL+Hkt8<%g~xUqBNiyJ@R*t=0yA5ouCUsP|b zudTnkeoy^l^+)U9tpB*ayZ&7LKk9qyf33e#KTto&{|(^&SA_io@46A^O~ic+Y3@c^ zBl5^VUb6aL--vQ%ZVcUc1?3(_`6~cNz=jKeX&YdRTYm{~?f|^w@Av_*uSXrk zx4)12EnllzdlGfeTJtmTFuzt*djxp#u^k1DB-TIG%&WNqylHMb z4;)5TzfrZU>MHQ6t~^#@thfwZtIGefI)C+GX`(&c|!R=n)Jr8Aa3cWdme9ZTd(HZT5pQR$)+ z3$+UmF9=<5?=8R1H_SgaFJ)f)T)|w+oKJ2}y?M{U$=BG$C-p{G`^zGYR1d#`ptqU&oG* zT^Vz5{5R3D(JP}KQ+*w&iZn*-KjT!{$GK^rz%M z?RomzQ>LdrK9qjwp(nkcT=T^FgT)75c|7s)j>mi-+xTejBPEag?LgsyH}_B3fB50J zhxb3kKGd==Xy1;#0ec_l^zVGIBd}v{-0$;%?h+;qK;L zs$EBS=I%Vxd|R`md2dsC)2BOD?GW#HxN&CV*#|c~82aFA53G2=>w!b}-+ce2`yRe8 z|Gr+hLzPv70o-@WGUjJvPg z_3B-B-j#P(;9V!T9N1F1C3A~(%NKV(cIVnV^X_Et{BiSpoA+*Bv$=S4{ARDs7dE}I z>7h-VHkEABZ;Ia}-_+OeWyAXoM;i7vY;RcCU~X8{P|z@=A*CUo zz%&qCLfm^JY%JczBF+rNU4%62kajQfcprK7HOP^#9{F!VId5#bu*nPM7Nh*VfaAx_ zEMQs-*uJ<^3OFkP@5wEJfc;L?;mTbZsL%6v_uV}O^?UsuG3vT=>)EX_sQYW%e1V52 z@4b3&5%BWs_I%*z(tS7If9QTM;O(^sLV?4x56*0SxKRwee!3&QX>XGRxIWXIyYuKy z)vo4ULbSuh-HZ2pvPakQVoP%C6RnYL9c_yCo$Y}g4|e!>KF}GkcgNnKeJ%UghxR`d z_weC|r|f@of8l|@9VmIE_mPc{`aah2SmNWaJYIb8{J}L(ct82jlj(;(K4g08+EaU; zPX5zJe=`4Be0cw1%`;yjwzf61K!VBA9OnvFhOLzTs z;>)LAzWbGwSHFDqzSlBe|HtbsZ{)st>CGqJTJpBvJFmZEeK+R4)9*FDuRqp*?8pa} z4S_9B;XlH@{p#B%zq{?98Q%|n z|L(u;|6zVF`{P$XKJ}CB=V`x)e*O5@UB4~s8-MACOD|mBbS3}l=>9YPj}BB`n>^_0 z|NsB)|37FagkI?#gm~lPa9zT)TaV1GsxWaFg;16AKN%0ZhH}e?hjRRofaJ`XQ#=PF z(c!V^JTnG#7zfpsmtsT)Efs?!4Eid$6&Mw*sxHZ&9-f*FG=fSbrw z80(zBCgXMEYAYQwI)~LmX{l^7n;v?k{`3-`mg7#YV{W&>pWsEq38d~O&d zq*BG)jXS91CYy5vIuvF#R#c-1SN6kkE2`E|Wqc@J7KLO8%Hi;6Cy1q{a+}dvDi_Na z9yc6kPHkl+1*&9(O~8in`N;f@CAM0a5olErjj!fV*`+3{r3ORck#(=Et(c3^I6w4o z*N-N2j+yA-hPE(;h{x?vUKLK<50&ChOWVeo*4Y*%mA32b6?18O{H_us;h&8GjHRm9 z%0rKVlFe9I;%qs-<$qV|Fm9Y}SX({Z0>kfUeQf*ynOY!jWGDH3>g)05eCsw^l-5{4 zycFg?(zw%Dv8D=*xRN(uM3T){ zT8i4XbY@ctHBRvM6yCzcRU2!J6(*1`MfeTIWw0ID7BDdD$9HQ4& zml|!LT6bB_TJhOiT`AUbE32wT@Aae>3D*F47Ez*Cs~Oe~NQ=oVmOVprsFo%`=0GQFbD5OC`ie*g*B5 zIm+X((BOqTpK@ajS~Z7S;gb2JH2IC+r;H4rXMwEcnR&Q;o=1u-mD5M0cZM13XxJay zk6N-^;*&R|&0S|LtXlb>3Ga2*@~V}*z>bfP=jNDTA+0gON{Wmr1D3;DWwlzUX{j7H zTvZuY0doXsJJuSPNsz|LEu*N4*(Li}+_aSg|(A;{Ym#^QI7F!-Y(!*QMAG(=9nNB}OH zhbz925z-Jsf^dm(CE^+c1Oh%5A!G1-eYrFiAzrv>K4H##6ih=1k>GNNO9+Dx4IyNd zE8GQ-kO*llolp(K!xzklkH+^fJcy1z`U%7}9G?;3j}NE0(K~0Z6rTeAnZi!P70!1e zB9ijY6ie=KAz?&}$cZu0X;<`~dZ4W18ZaAIs zDZXwL9(;pviWgd6S~mSS>r1JT5L(~ghtoK2{Lp)Me0uN3&+o%2JvcFYeSAvQHwvfp zcB61gKQ{{ZLpa45Z3hbZ;2;fg(m$m`XSk5IFdt5FGaR2V?r=B#yYd+dr#PVapklD~YADj8v^DLj>2S^*KV`IZDVjTw`!m;CTanE%<#Jmq;iR4V#!J zRGMsL6hj0*2pElQ)IAO0MuCu-WyB=IVpC0(J6A%w-X!GVrwMr$zwhCC1=ka}w&8mE zEkbtT_byzypAd58V?tu_yV>;{hI{ujeMc`EM&I8);+lZ4e|8aa(RH1{?=;tS9KY^o zdQZdYbLNQ4cASvIUlLM?YbUPT|L*+VI^vnWqZbXM@2f{#pPeJ5;Tu9Kzja;)+~@cF zpKh%+Hi{|=pXp;3aAAu{V?&DFhN=)#)0yoP+w8Wx)Rxjx1cE#w2$Z%$!DuMd0J~C* zkbsC9(MTf_2og;cLk%JcTOm|}6v2S-1GC6e65=ASXw&dkns?;;xG4--#v=bZE1 zbI$$d&d#03j@h1uZTW07&VCKF)!LEg#grAH_5G&nM{z*;xUul%sRMfdx-*+UKe?sc zwezD>qwds}RqVXw``xia?b^Kl_@I3=AMq~vWd3NmWq2WClWUC1FL>NZEsG{l(}L!4 z)lX4@qPhx;ic3n%DyzJ{an%XHb93j-Z^G|_pEe8`&0;wNdToX%X>p0+m4@&loh)WR zl_4pABHZu9Zv3yMapL4!{52Spu-i29Jf@y*YR^VfuRUn$=QTqI);v*3knbLxXXrIQ zY&LY$v16>Av$v*HL0@gJDPg_s?GbIzo=aN_wn4w~@S**up$i|qz0mHZK&YhSV5OI~ zo_TdzVY`>UX=rZi`PfSpo90}6=DgRlzI*w|Pcwauzx;Ii;)pumo2TmKk*mRT1fnX@CMWPJ-3kd`QN!fuwFqj1WQ`e-Xh3?72Xc*5N(zIhs zwt*WR0bMsk3@FBq)%w@hVD->64R(Tr6C@N01}GGXqNpD&c9n<+NA+Gl#X1>Z5w&cc zN~67!j9xRu>WRg0B+{`Jg{QmU7|)&Kc&+!YuIJ=bL@-m@ zij@Y8jo=3?!_S>^4Q z`@RiuQnE-mLvq}Z9EUO0R=gdy0mNpr z+q1H<0|`-9`Ts(g-`g#8$fxJ&g!voPj$v{vBZDv9b~pTGs73;nAQe-<%cflm)=<^pd;?p4&v1wIA+ znNK2S7M_8jL&%kY-vYOMzPLM80;H7Z-~!Ey~FT(5YrAl11%qO;z9of>_ZRc zc_{3$u-^j*4R#d!@FnKwG#@vNwF?|hpiVaSp%!)>_&kd?2^_l6KMr;#Y92xE$qVM` z#+uJTMf_E&qRV$d2~wJ1!&Hg|-z6p&i^+;AWUEDDvQUX?@S%#+i>WfjbO(G3H+9mg zrHBiWD!MMwEfn1%(JdC;645Oc-7?VyjYMLKNJ|lEDIzUJq@{?o6p@x9(o#fPibxB? zCbCjRR;tKK6+MRT@jU z0lWb5CauQS#W8$C3oe9%$?0pwhh=dT=QZ%dh_}W|)_gYKZy%ClEq^o&KKD7-Q{^z; zXAOyAj1PK%@Hm0BI}M!JNYA4TDJ?HWPS2A`O3%Z+k1hR`)C|fPoQ8*2&b6hdqoWR-L1QNm}5I_Vk%PuC_-Eb8#B&dO)T}10rtOl{V zpw@s|Ljsr!ig&rG>DE~Lu~e$PK(XyEmrsF+U4>oU;<5ra1xnbNTNw1uj$I zG6gPE;4%d+Q{XZME>qw#1uj$IG6gPE;4%d+Q{XZME>qw#1uj$IG6gPE;4%d+Q{XZM zE>qw#1uj$IG6gPE;4%d+Q{exJ0s$h@z5Z8+!vEj5w9N1yeJ*|_^WDTX7r+0}C9r-v z^t|=Oi|l&{bJc+oGy)xed;=U3#rhARbEoThWJ_%A@4ADyWe=A zH49D(_*)L20&Slb@41ksR_mrEG_{7HnZ;Q*)RO~JG zbop|f@$jiNtWEDa-E8ujhjKbsjr5KhdOo=-&znE=Y`QhaYrIg#;LRR-Hh3(nbY9(1 z%Iu@?EKR&e$Mc_luLnC9P;WUM;C{Xvqk6PvB6d98hIgD6L5$|@_5{1GXg$fKM-Rpb@G4a*QW zEEl*@=rs*dZ;uJ0Teq#|-vrk7h_FHVA+S#+Xi1jn_u?6GQ^kqRWEp69Kx2{2^xLyS>*Y;-KEVp?jQU7 zvS%0cGsjH*W=jiGy4Pj#?-uP#pI?^AGq-Rm;UXp74ydk2bqBRbw^Fpv-K;Ma@|}>eLQ6oP3)w&|-UG=|^`h01XeD4x6>Wtkb3S zKese;*I{OklEaqn9?GdfEr*%S=0_b*Hnok5+_=qp8*r^OIpzn<>Xz4BYJcR$Yv$jI zynuPM@S5YtP0s_)mGedmN14UuA3Jue`1nR{S5y6rd0~dL&2sQ1!?<~yruusaCf3n$ z>9nnR>0)Q>i_K$sO8KtUa-gRbX zds$1-y#3X*4b0PJ{+E_TZsfL)oOh6+@3^N;!fpri^zNn=OP{aLsVzq9bf)c&CxGX3 z%MA06GVSKa9M?B}uR6n527IMl%^w)f-Dmv^*z!%M$qpYDU1+^t?TBjeMPO@R<;8$d}M3G>M8hQ zHooA6NDbR%_i^21>$26%ti|TXt3_doFk8qA;!U^RN7~J+Mc_3axg7AKdCaw>{a5BG z!7+F<9=UJTs8H_}eaviwpx%?++GApTMHI*FfArY}tFXJ~3cOYCFKuOJ^FC&KqlvT^ z1<(1OMLwlI*J0R~Efgx4W&=~Tz;9J`Oc1!PHKv_T!)aAl6|lCfwgT%)VHW7aOpDZ% z1ix0=dqtn2gu7)#>D*gbAG4KgBi7@q^#XmF{CYZH6VuQzSnwCSGr?s;#8@qkpufNtA+N3>fY0V=`JUPR-qS?$8!f|hqzlkp_f z5iwYuH>V{jA0#3px;`eE=WiqLK0wBE;nypeQ%qHV zP-Say5qnO%+NNvQcj&vkK~)7G`hh2>Yq9C*a_B_1o}i|q8L;^F&A}1fM@&0{J;Cgb zDnVP-6I5?Cc3dH7ckn&^nt~H$K4yY0tm#(wgiR0mbitj~vw~%Up{FpC-CY&T?XU-P z!39INIg-_5=z7dq6rx|~|Lu#c9{NqBCOe|-$?h(~7r7l--FC{o_IFp8f#SK{ks7{7 z+tsM$JD4l7%*O5+=APg?!8e22j;EZz2Prwa_?)j^amID z`bnOz(bUzF+iq#qZROjStv}t;vp%m~zcs6anZTcF49-XU-VEk++~!hsw+DBa-wYae zkg?i!)sDQbZ-S3GmmJOM8qvMZ)a+^x9y4XP8@qdg`5l^eGEUW%2sW5>T}M%B*3s)V znlRtPcjtC7RhySnTJas~?mV?kp;IpK)OIfmX7wyGH3YMJ)|s?+ z)1BXw8!QSMx;aqqA`LjuK;5P3_LBafx+5R$XRgq6yc0Yypz3C3TyFwjJKhYwJTMad z;A_n7Qs29)AMNFZEP;%#23Aj9uBJffl5tz>|`c&Sj$W~%q%u(tXU3Habswb`^fT(wJ!+g zws=u{Zc7$w&u!^)WeNHIxe+qn*{@exea)GRZ6@DobLE*(p(7_?I%q6ZT0IA?W*v;! z=6E-V9)}iYp@qfa{0K9_k6b(?kIB+Z$x@RsrvGIIJ?5!$9Fz{y{r zh3x5Ll#@2H`NR+>9~$E1-pC=e%Yk-XXVVcVzN2t=kYXw$v&)=Lbmn-ThR$o^bllT*S!n9gJ3+WS zkX()QL*9nu>UQT1id<<0i=dr#G$U8zV<$7IqgrO_QD(DA1I?CH*K?k`KAkw{*Mmg)IMfc{$jp7P5r`VT?e^Z|;|)rRhhU4X4S3`u<9cJ=XNY&g)Op zr@}N_RvoU|%*?*2Xx-+Cpsi3;5>!W+GG56oDw-e^2bswQAu`z-VkgfGpDk?6DKhsP zi-P@(#`cw|z+v(-w&xuMLc>i<9LsMQ7rC^=S7?RNTi|%bvHYfSu3K&}{oC8j_u32J zKksU|K@;K1-U+V*MvXWhkkU#8fk$Gf*ulnoHr2Oi?XOj{aO8E@wy?Bf5Fa zw2vMv6ExDiL1HZv)Y3V*4CT~P1hGa63{qZCKz$jl>mlLPy)NPOy}uX6*b_^6aGj}| z5OOK?(YiM!#|meMQra0B>AvJQ50VOfc#Jqx!R-f0`-QT1DDRA+#`%?~FPi4}QEQE5 zZKZIdTh*1UIAq`gR2Ds^@yuUjx+pCxF-xo)-ekJM{cIwRg9JKdyB4c$;9er8uoe@hYZ$Id&$ zCzQ7f<$w~`$-9-fR=!q==gP;F*db35D3q&YhmxKtKcU3aWKl3$>AX~6m7^17QOPZr zi4vE}&ndB0KBUCO@@XYD%XvyXQr@Vx1lpjcEW?CvcB=0^#d3rx&Rz%o}FxY2RWc^q=gX^Eu z4=UduN!yh8_e1&bQA+~gy^}r*`D+X^Ro2ia3TG%+K2Bt0k3N5pQ22$Xza&Vh$s-Dj zZjz(-rkUvhdp~*F`7NX(!=c|N#zaVI?t*6F)Ppl23mSPgRwzY2hqbeYjNNC}d3u83 zW?)6a!~K@F%h(ryjit+JIA!oUwWn8Pc`O0TkB)1S zCzwj+O1V^>n?o%7mPej;~BCPf#NV1ILHJ6KRlkL zzTfw11l3loI48~w&DIyO0b4q_n5cJ~g>6NAhe2vh?01q=6R@6YHQNMLmqB_k5x|O@ z@06qW$N?MQsot}g$kBG0jODw2MjGnXdm8Jzo!Su7&UTO;oTzbYJ)6nCc|q zGQla_q#?&yVWCir*ogEQbte5ZVw%2bC|x|1KBF3Xk63v>lrA1hpW%nzBQ^@}0_rP~ zz}WN52$$%iqvWQz(ay|Hg&S+>7??_mJ}Sxg4&|a}_%xC~POR5sT>2U|O_e}%z87D^ zlM`)`H9TW$G~^29j$4ei!Ys7m2a!2KgJ$&!k6_ZQII&1Lsa}TXPW2)@*Q?z$Up z!zI2BpC8B-=vU{Ce}jAq<%8qjDtRW=aXityde!?wd7Y}?4CS3v{c^aR`iixsz z)GrQ~Q}4tRgE~waa-w74Ujtf!wv(LLGVsm7!Lc*g5w4{JoT!JDlkE5tBx*)NS37R) zE6DquUF%jMS1nCQP#ICx?i`?FlB0ql(-6|IMI3^hQJaLek9AW!EVc2=*Al|{q`n4X zuY*01e6;kesllfa#9HgTBMf6LGHrD{)XQuu6P7i}R<$%TDPugNGnz3umQ}mn4C+eC z1ljrnKJSEDQsb>!dCMec;4O32o3PG)9nNv*csTJN!1zpjwvXA_KrYs$uX~fHHT4>b z%&;4-pp?I8JEv{9d#DZ6RwSX1JldNrWMP)lNK0cz%uX6k{kiv)ofLrwU!5>eM(Rey++n&RqLWP%W)blgXcjIdPla0<6@MJx(P8 zYXpoH%@`}>D4p}l7L41Rp3r z_9OlhAqm;JY63%2h>eI3Ay4Xat$!3FDy&_wcRv$(8|~^#@dBAd!hI2&@Rqw$Fi4>o zQ+hV9!ZB6oQ__cGFDR*>DXCw_nw3(Pf6{M%@p>chKEyA z1x_GsyOrGMVz0PoqJ8UAe49?1mCBO-kl5kf?xA{>URs5;km&Gi^QvH<=XaJ1WSeRy zvrRAEm{Rrd!YZ-e1^JS$NwBaQh_C|crPFej#3uNjsRG-!RjK2ySesHuO-du^BrRZe zCVu3-f2fYBNPix`&$GeH57ohJBTwn2u_@R^F4T~HNez2YLpXlFn{As4JO6CZ=$cqj zWF6WzDs``$MV>*L9$Tx_nXR;Toq|V2?E6X{m-4$gNE0n*jnTFLo%0QL0%&)*Tiwxv!$pYldRiuq+Tco^+49-z7eJx43a#u1-lH*gnlZPnQ zh4iBMB+sNvxWa%hEco(R@>0J1AbycABS5to@yAh9BjMU+D)sCiELZBeFG)Ew8*q=r z3%w(U>bVu^;&_3l-~wmJQ_NGemipwSyt($0TKdyj5*N2E7;Wd;Xphy1a+O+Y8T6uW zJgf3C4S^lk-a6O3sCpaYpnbwPi6ILo;`}#)AK`w4#}Q~h=|r4H+>4lwy&oXfqI?O$ zOawYsH=!@JAUuxnEJ82BZxD_nNC+an$!cX=jeQ}@uM6jz>Kp;9j(yyzJJk()i^|PK zx}Dr<=qT)BQ^-Psif(|Bf3Q!39$*x%6h@@d4SA8Hr{pUIwV;MRb6l==oyE$q z(I}a$!o*gsv^r5{VoyNtW3dMl96Yd@)Y_ekSSOQ` zD;xDT`uqx3I$Ep@oH9S{kiCcObp8Xn2c7?~lm`!Ji-r1fI2W*SkS50J`zBOO?{bVNelU5R8pV?LvDJ(I~ zb-Y*|C@EoIyiR*6NZVerip@8(k$~u6XPBOLPVDbV~S=`~2f znrh8{(?eqeZ}w>a3Evonjy-^0f2AGt3qIltYsb zU~E;pHJ;zvRniZ!n(A}@vp+Pzb!MU0ts)GmMVnqjpshZ#JRdU_snCY*UIdJj*L1Uz<50B0I6X}W#23If!;=<60#x9*&dZNS7!Df#-6h%VBVMJ zq{j=y{!s&4l^fu#ivo**xtlx&t^a$ym6$jGJXAM@mEWiF9D>GveEF+(vP~oM&=3Gw zDpG2LzKAma8Y(aKjjnsc{?gp1hF##L1;XGg)2Dy`HrZtA#Fh zFKiL=wXJIizlWKA%VK$==1gvFz^1Px=5}bpH^fP4RVzD9HU;cg1d7<5&cBAI2>M#q zCP!=HOxGbhW9uP*Sn>$y^YmQlz?Ugm7A9wCMsd;}rZS-xKI>XhTg0Til*{X@`KIh-V2Jd?f9Zn`p%DFI|S?gteWT#!@p|xm$;mUNT%^xrE zQ$3xwaT8Hww`GL`bwC^I7VGOz;EwMu=5#*Gjja6QpG z!@zCjF%DGne7jaEkNr?kVPq@gwURx?2?wBIAG-Qg@+Nt{@q3Nz_O~#~IIw?4N10Zq z_S93fhn3#RK1h3*GRkQ8sGimbG`n?s^8>1YejoSrm_XL+R|j4;lc(h9dnvYSUF)qT zbMW@oIzbyM2;M62p~s!%v__S*ybt+!XJg#3UOdwi>_ z<>)Ti-dZM91g<$S*oQqKVNwg7>uS=_Ra*>_D?QV~hsh*1#7t+VNm%tg)I@riruUjS z!P$g)NbK~V^uyx)1}r?iHT(JZRge?e#_rC7Wy2=0yKB0bZP}7$@JpXsAQQOIuY>IF zXR#Bp8+(HK5HpS4n{Q@jn_5U28`|gVtoe4JQgHS9f2sW?*K4Yg`qtKs6keLkwXs`A z3*{}$R#*VS%=Fkmc6lO{CFo`|712|4{L7NorTEeMFw>(^bfkA8R6>80nqVRm^r7Y= zGHw^7VD@A_^w~|hdw;QnxdL`jTkgKoH(0S}a92oyJ8f{_r_MykR?dXRm9t@H8ukDp z)Do2?%}tRqb(s19age1fX<=;MCo)Iq|sU>BpvB|QCuPUoJALe(nT?Sj0^y>t>OZAN53NooUlndT{gjt(yGYL#bmeikQyEZzr z!nwPdE;;&Tn)U&%vmEl%TcZ)OBK+HMEq$G&Al&=S*REBsy44$D)_f zC!>8#2j}Cdb+Ns(rc@X!$kTIYkg`>wX7K(6pLlm?js5=YijwdPKE2pk(|kXv7!|5m z-&2tt+ShUwbV$)OMVMEaCAB7Zw{TVlGmd$1k6%QugTB-wM?XOypW$Y@p&zG-{R@Bd z-Q(`pPR~7SC8fFSFpym+~{bWNZd$KVHzpR31MX!9h-*56qwo4RL78`qmky3wxmBB@E8ui{yhLElOaoi!eUB^Ek=hYN{0Q}H`*;uR zUhbpya`cZVMc39oyjz7!eI&d$_Ko!X4EDKJ>_vv^wbI|ydg;Mbwl~Y8!+dP;7`!^E zP}WPoPpz)L&Cc2wX+}~Mbne?R^1Vdi^-?Nf?x25xdmKtkq-$s$-vWLm=8(<3@PjDN z4Uce(HeYp?R1q)pWl8^txkh)+SyOHLp|6^e9!+U$IcZ@`hZ&yNCdj&Qa`DbRMQ~vq!7K|7#a9pM{n)*1`x=J|%1f?Dt}t(W=Q6CyVBbwkZOw z^B=J_)xPRm)-lrJ)F{+c6!UK=7gS}VPimwuQk+_6$jK9hTz57`E2CSl{A%!<Pky@stj7W_}YO#_Mks5=PS4laL zDic_@4KjH=NyM24zC^u#&}(!pFa0^Lk)8lQpGZQ@k#4p6>y2`rRhn*YeB#9ri(m9 zz_&T3mmW!|+oC!X{kJ44g9senHDH=9Jnnb&zH#cFpnv}Raevg#e%BZIPF(ng8+Hg($FM#~N-+^3{s2GC0`x3~@haevsg8XUXyO1jq z=#fK^bK@uNrvRH`{9;21FStbDY)KTjv7dma4e0L_XCH8$49GOE2atJ4*V_tYacIPi zV8l(wb$~ox!TB6|1NE%S%;}UDgxojxRq)_{5Pq-l!l3YCIpza3>R>dv5jAAE;)d*aR^+UYN$ z-LK*qu8bd|o##Jj_e6a91=_8P{S}Zu{0`*%;~B1Kq%-nGes3LuoWkBVovn)h19DUR zB3G(o5&K8~!IcH^kqTEdQZL5iVXmwKWXhEgAXBbLamw#Yxl$F^U*L*)h%3iIf2Du_ zSHAqWKC&DZ=}aHFF*V#r7N;)u5&i-$Si`;k`kSRBGL)<9;4{qEMyVyq-5B}f!NN%4D?RRyx z3e;N-zX@K^27tHtU~k?~-=b@Tb$!f!_;oF&*8VqO)3A0oEMQ(|Bkz zf5+Yn=T1kzku&QMDn}`lXD|zHbgGn5dSR0FnwsdB2dkTu`4PL^XXse#N>bhWV33z4 z!Y_sDeyzQvTo)eY{Sq|pYWNDj-Izu6u2GmZEDE&pWX?R%R*q4^SFM+pC4JTW4kEoR zXMrjYCvM+Tv4zeWpgXYI4Xn6`8c#34jze{(OZDGeta-*DWa`BZc6na-bNg7V_D(D( z6Pa*{n~g9N*|6O`UYHi)kYjVl25j!=08?J6;Bq#>31#%$&l$aR23ih$k)%_J>zvF) z@uYc3r`JoGB-QDQ*AdAl7XZsCiK!dljfK^}!L5xj$`g8JgoAgj4qQt|VFwneKCcJn z)kBzP>|Tq2ZwtaR2nP^`^}I89zSs_Z_!Il+3+;euFCw4~V?o0*1@A{M!F%Hn-ak_C zHl57BfcL(Hg7;b?8RQYb`$T-|dJ%r0OqiZ|qVye1XYi!Y|HKYmMk}Q>o^~xm<{}K^ zcLSa?_>ICEOBX8ko>Msdw+kFDS7zT?!0fb!J;A`2SRG+1;-?z5=LeXXa+&HBUH7D; zzd}8xNJa*z1k@)gAxWbX1Ufd6ex8P%R0_mzZ>?y}$bkmmya+rm;oXYSUAo8EfH*R0+*k3r{2+_7&C8L~pYbNluEwWVd>+ z6EvQy(D)DW3G;FU(Wb_#SiSo}qL;YDdTk~4RDPJI`W@EJNu5-j9^)AUXjNDhnCQA8 zL3M6zn|e2q7Nv{P7E9c>xdPqRgdTi1>g3Zo-VrGItUSV#gD-a?uP)6D;qi77t5<>9 zn~si0n>nli)9`y^#GL8mT_ZsOINf&a)M{MP~h z12`$9g${a5)_HWm=8L!vIy@`9SBMjFQg4F5dJ4IKmWaPg)+uzHpzx!8R35Af#irof zfmDVz*8%pEICW(P?3ZMV#{$>~@cyq!vl}ygo5`aQOPr$gv?AA-^7_(cA zQS19D+ONuEpKsZRQA_8h<5oI44`aIyu-q7J=_o)Y*p<3CemwxZhIQEA!ym2WHN2|IUox=M~ySFVN=V`0bA6D0EOOlvoc+u%N_e zNy?8G2S0D!H`H(Gm~sd!-OTv?9=z#>$M4~`Pe7e>zEkhNlzPAYFZE{sTfJAKUIz8P zs?_Tnyf|LadLO?~@1y^v-g{B!V+h(l0*fsze>Y0$mGSHNAS2X{-Z7idbM<@`tpB8A6?Szsq6>S?y!39&xnQdB_7=^nq$3Dv z)QH!*dFkh|GFVettT!uKVN>n6&8`t=DdqRZ-rho2I~9R+^!8XFCGpUuPq;fsEs9_@V&Ll>m&#R@)N)6P`s*!F< zK#$pT8&A~#8)6to4{hk-$%%d zcj{WT_r2w+3Tm-a!D1I)&PgSTeSq>{9=&87W2K+k$8Z{A47mIb^g|Y_x-9gyD)cp- z6qY$5P$gHWPMO`9DN@;#o$!7@s=8QcbFZ=({1c?Q5yNv1(yi+#0%L9$Kn)_bzNS$MBbTybFD&4k>9a5cgk z21sua5hH;06~bENZA93L(3^#KeMT>_Hu#n;U93HV(~#Mo9+Rad$Bwgzpk7vO7VM~5 z-gGpU$f{LIOR=g|ht$YZd$p+T>x4X@Rn7-j!Y_%!qqb;T53N(F8#<>-dOmS5s8#m6 zsSc`=nl4E*0?jciIk4s6J6c8!4+Z*7#5|lHb4i+hqn3)4oP*W0Otg>K^0BW!avrfx zE|yKqQ`j97m|fT2#7z5T^@_QhgI7(6hQDlh+-ZPs&lYI4|1h~*8SGE#;oE-Rw6=At zQ*|<6byRJ}PI7-ZeLz+BgykjYw;#~={~RE5!5;@99+AMVO2quS0 zyajplyPP@U0hG*zzZNI$ldXcoHWM@DUYyZ=S*~mX9V5h=$=idxoycRAne*mqR7wMI zcq^NT6Vyapjr0hwzpn^8fd+VDGib@r_!XA@uJu|hD zVl#d)ToDij{{aev!kURQ<0|;u4#U_g>%2s4Xf+F)uv-9O{%(eTV2n;l8R>v^+Ejdd3-D+=r3A@aJ+T*C|h7!ZYfkRq@qWZ{iY z`upIW-ZdCYAA{aBJI2i5g|7y_Dg39Y!4Ze&KsRO_zMC1Z4)O3~S7QgO-3*W0$gOt1 z4ejX0NlomrKI7z2O4+a9(co$Hvh7?4Q_A!_?bMy7>-r_$>rq2PoS9Bn|NjIIuwM@@ z_AK^hL))SypwnLP1=2|G0GDqE>tMT3OZ(6U73xiwGEK7Z#1inPAILfm@~3>}RU5!&}01Z*z`6O-~2>8hh}S zRkQtk558@;yLhFA+Rz(Lb(pq`3%xC{9h2-E{2J*AJ-qhBhktPl@ z)3B!76&|2?m0@>$Y)IWb%g^-xNZ=w9?e{nj0IPV(i-ew=#cB;)Tno!bbYL=ez>R09 zg`AObH|K_j0wO?Qo@BnTnntq~6rDuAz7LaJ7Q%Gv(c< z7v8Odm%^RZ->+V?)>8LP;E-K4y^%z4@|{61JTZ6_I?8bBPlF#{lKTDN=}S@v2Lq7g z;gY`?{O2X_f`hzQJtKl$WEL>@4c?>RMEyogwuLU0_t#5JCZ~_iTO8&sQ_I1izb4~1 zOV3qj${728qm(*3RLYE7KrWV%`b;?OnD5D-zklfs<~x1om^-x<<{tBC%z@{Fzt`}` z&5mbq;;qU>B2^B(dxCkD$?iAV>s|Rvji{U67NGJlRyu3q-VHyskJ5A9bUvgwWcDJi ziBlfac^-QS);SKX$V>MnFeCQmi>#HG3KAof*qC5Na6&Rb1ETrb1f#?}{AX#JBse8b z#;Ff4FAXAwl~7uepuWI7Y=xP)E>WnYKaEqLU|yP=Fe&Lsocac1uOmTygL&y>T&2X* z67)_E?AgTCN_s+q-pRpBhvFI~U6P=8a`4i@IK7jDhwmu8lY_?|HocRB;?FCw5i!l* zk9->Mj%O?Ji*cCyI(9usFXI^>df$(hxn z(B^o=WpHeBj2CRK(<|~Ko3wf_SJF<7nncGz`?HQ7BA1+~A1nOW(T8#mJIVyn6rIhWge21#oA*gy&^3+c9TONx%3V1K4xl!91-2H98o^{`$Vr; zx22cP$0MMRn=xBGYv-g`f|)ofROI~@wuXNxwuT<;1e#o{tSV`NJPIQbX|thx5M|F| zFGdgBRh7?%JzvtH5nn{^N!UGf()00EC39UWXmcEPQJ{Ioxt^WQPeR;oZkrsvCjAli zn#dop-+@5;WDDX|2y_iqi8+fY!?|5=6j+@94i*NP?r3XKhd;gwa*kQeO?PT^(ylm* z@t+G}<+fdp8Zh&IHb7x#VA6FcQ#K}K^ZX6H@tpNogPSbI&JWI0RE!I;2t0xo!H6It zI1mCfVAV#%4rfVdxaO*OF12!FH(n>Lij$uGj-99%b{@3t-Bg+I`2Z0=9bm*y23YYN zy!byJ;Kj&*O8js@Eq;I-PfibL#ghtdhtOVQA9ivv<9u#2co&n-<Fe3BZtCRKLlf~9KG{9FtmNyio`z^ z(;i^Ftj*GdGsciNZ6D`rgpUg3+s*}$*P03bzAe4%tK5F-z41?Z47Kk_$I=;ZE;;(O zTr^LZf1PWhVXANqJl0{4hi5#8{#PbYX(~&vf(GMq-DGBQ7fOZ6<;VjB9sDur!#3=-oj~KnwPuaF!MFeP#!iv>{v`5Z|Yi3CTZbC%0rh>=A zb_{aXF^I1k^v_?5m5xUAdpT)dY%KZ~CvBF;;@zl0{7bR$ZzBaIe1uHUh3c^e*pixw zSu&Aiu8P}9**BnbG~Ene;ibK$01BhC{Zh}}|mi?_+$+`Mv44?OyN zU^~HC3CSE=>7!@-@?FhM4CW^}`ess&n$lB+rQW50#!1@P4RuTBQQISt&c~LxZ}8mU zg*GqM#+P_+Q0n8P^Mi79!r)>rhcTV&nkp;;247-rj(udADRYKc+@`{nEe1!whQ-JO zr;*AyCp|JqXG}Tzqhz^IT}!a9DMwGFu2W#n1%xAmbg$I~FMeK{KIrr~y)N{4B4x$t zJ|QRRFdkhCSbFT;5a<$o1a~??Gb2(cNynHm@Sgb=D+ppG(qQbT1Je~q#=&VyY#6L^ zPxDMu+VU|hNQ{&XT;rkL1C@BsNlAIK5)aCgl=xrrL^nN`K;i!(mL8bs=0U*;!1LZg z#{gZkJ1j(`e5n@0*0bwRW3Bted{tcA<0O4N zAPfSx=Kxpg``oqyvqz6Ic98H6>`{>L-pEb3lk2AWxG^qV1^>ev6#q;%M4u;y>gU;8 z%7iLEJyBzC=|tbQB7Hc>N(Gq1SoqOUzYcCU&J(n&IvDBc7>83-By~qME1>6D`Q5gM zUbqK-;e%=TT2qcE6Y#xE(KUk$_K&Axt_4KAx}_Yv>x-{%VQ_=lPvh4j@5&ZA+C7xB zBTgp%B0S3*u=V`tDAO41cFgp)XPs_(9doE0{b9Un9tS&Q1+cs;jbg9Xb~+c%pGDp0)o?nb#%okswfcpmIU&Im_`ph-W(P6BDjULOKE-QW>kK@A~*+5w{$T!rnkK z>WAdB)`X(RFo?6E&tNRW6G>kQ8z?7rAg4gdiKeJ+7Gp@d%trf1BKmcT+DSQSBg!PB zyJLfjZi;iL0@cnroS&!KIVa6YQSF?Qu1?tnQaZEh)>WUZEN#BEx!8}hW&Q%OTqs@j zw`Pn#sgZc*r1De&DD`G)H|9yvKN8Qquzu2K>Y1zwiN&n-DjQ=@Mjsdy{i+Br>fAby z$IeRcr)ddQn8z6lm1jP3-b<@$ajHe?!l`-kNAwv4KLS0IOr{&47x67*0uz#>Kah-wQm*HxiA){I|s8<}A~j|-e~SL0Ts@+(6h38oqB>&#aB=pJW5NWeIw zm8#R@*N~oe^GBBa)yx!T8mSONOqXef<%-9hIiWRcb~--~=PM!OKBIN_&iWape*Vo?4Ze3lyW#gv<6km#W-Jh_} zi6HfHEstS$o>W{BdT$LqyZ10g)h2laICl(|&q<+tJpBnz=5W&;jGc3i40EnWN|$rpnCNR~@nRKnEdV`zreN>-c&}m_po(Coa@{2W#ta zHLs%QW>((8+KYvejw4~`f_#_D-Mng+@DVI}tn{1I$~E>ii*Sq6QLK+Fxc#XqL^@`> zzogcFj6QFq&H~@c5ck>@ZrdG|0=J#tuG+5NuGy~LKK&kchgRxJHLtO)Sw@avRzGH% z?4E_a0*&~Mo!P-k+yCud(Q0-N17GXEHJ7gX*+BChjDp`w19CK1UO#Xtl%my`U8vvp zC6F6dL(;}S6)MCUhiRK7q!j#D{aX!rgcpNR&+6xl5!jjRM{mcip#sy+NWRpj`ISv;@lAegw(mC#uqrrNlev-V=%kNrc z-QfD5u*7iAR06MXUiyceS#6v(vFHoz2dnHZS5c9#dY*eaJoxWUs=5x}t`*p=jP!YO znrFIKCH?P^hj{@;WO|2V1uq&*uJVG<3#oVM62}dWvABW2Wox^CI@lhWq zEC6J_tJ+ZtPZH{xo`RnS3v2n!M5ODUGDzLZJIKe}s&l zMEDzmgpfc`Lq3fNbe&~JoHLG)afqiQ%!ItsQN|LQX@3u6Lt)5{-dljN`&XD@IO%EF zRJriVJ9vA((-5LL+h`8P3SQ}pGY`noM=<`)wBEX$5%XO>NAs$tC7%zJcuPH%eGP$z zmZQ34*iP>^ZQbIs1Ws)bJ%@4sY;No3U@lU^P)ZaT7fqX#w6PWEmy<%}JOTTkgRC&aC1Dy|8W)zA4Y6rQK ztkycTymYTT)~6b639VQyu2#V}?n$e-LR@`VrIPZJ8fked-cH_Gl9DtmjfbS>sr`ge(+gBELE z9&4+8GVf)q-O4(Z+ViMxO53IO&|5*&b-BKN_U!ja3BT6tB%yrVoQw9O%{&4H8SR@s zFEF;kcb;wJ`g2IfR4=pj!|&0y!+*6x7n)pKi5dQyIO!(hCZ{trsmT!`K1QlY@X}}S z9sVpi8aLRgrAN}mo?>9WF|ENK>w_fH)S}f$r<0>_!dETb1220M-fH8Sm`D3Y=IGphi`^d3C^+r|vN|ufTaRQCv&UO$F>aPd}UAl>U!> zSlSjs<~x+g|B7R{jdUIGDdanea1eeWjF%|)BU3stUI#JZwl)6G3}IkLX1#%6CI^1h z$fJMSz8uK9Wl$wugO>du$$L4pX9S*q1slY{>i6m2@#ELRqC$9_JnbRjdRg4)3P9$< z3p4f?z_l&rs5K@-dzBX!Y?}qT?>}V@c8i7$1+L}mj0Yl=cd#umu+e0-QcDeko16(5 z;}yZphCuPqEy2YXdQp*=_KQT=(%K%h1PX^z=2ns3w;ag-x3|WjRNS_hu{>m`JG+72 z|J=N8+f8-~cgzo7DFc&rj-3S%2asW8I{% zWktg%|H;zZN%4l48}vM5Eq6_Inb&Q$J_L>Hu*!&0^6|JzDoOnXc8~wHoyEz7=U}r7 zc(PoZt-BWQO>U{uL!Y zyinq&-+@w%G9M<-pv(ss%G~mAP^P2AA2CohlF)?`z2AXiN13;ie@2-yuHk^eecC*#wqP?EM`>y0aVVQi@{_^sEA_qTRNG4qyI%nIBxf@h6 zeQFY+L5>{Ui}V-uS3q~U0=`L`pm%Fx)Z)&#a= zIB?4O<+0-z^$_2}^JGQ!nuX)*_AVOl!Afk=?j>d3GU2o3hRVZ1oQlG&6jVolBTaAk zu(?O$Mvxz)mg9rFMbUGR80{4cS^K^vqrIcuJF8z5_t+hzpL~Cb;Q4gnK5J3!VbWav z+LEuAFgD-9z1GFf!{qjbuMK2-smBa$g<#W2LHW0^O)2tSgMI}$x*v1Y-3SjO+<_pR z!g?E_1kV!?rXf6xG@Z+qAk0OmL!h=Tf1lPvO10jCmXZF^u=%My(_O{uHZIAmH5R7* z=$FHNiGDxWmo<;rv+5?dRQT;1n6XtZImlPq*CnDj&ofySnuMM>G2OgjwClEY)F)>6 z+nIgY#q>^4 z%~nz}4tAksAx+P+qRbt+7|YlSVXISfX1rU|y~ebio}9-S-8Cj{cQ;PlYCCjYT{vH_ z>o{G=cc|L=E>-tErW@zzyP0X*a4)H*!_bLUVKS@x5t4tO2{`-?>$dly)0*Jl^nICH zU|6X(ncYb(I3K1=5q&qsMc-8^9Kjvcyfi+k!}%G~q3toa8R*#t54+9aW#Dg^-Dw59 z-=wlTsW+c?yKZ}h@H1*l#P0t=@PLk?A;gqF#n3+n`*Pf*bVSRDx@`X&)nmbd;J8UH znH)5aU8nZd_}a}I=CDn!rj^wUPAsZIS)lKaQq3ERUAO)leFysrz3?9>9n(_mr%NJds%SY$MrJ#$gK6beaCXLS!P6!Dci-fHyi(&Idf=U zKj&B>FFlcX#cp_}pJWUFsOJS8d#I4z%C$Y>tUbeTRc}?bY1-IlxLtg=s^`U`19Q~R zXm+(1y*-E9m1kZv=WXYg&@0(zg3eD*E^zWs$%VhHe%)DlhJHaY)o#^cKL%%8U5wdtS9+C^!&^SUqaEx+q2=fKJAXFjlxz->L$PDr*fI~a+V4PHa1VV9vYUT+oR z(K}+4dyhDegdcYXPaYb0-FYs|cR%kud@=%FN<;jk{Y&aAu6w8#=Yj2l$L?pgJzkxQ zIlx?JcD;hp$GYw)`uC>#_v(Yz1{dYQ93KIFa(KqjW6E)<`Q^qlg_ZE|qUVB+6|So0 zrDXh*ATy5Y)nt+etK%GS{NW_;xqicJ*Y)eDt&)x{!~DQZLTF9>NJK6VFGduFor*EsKx!3q7 zZ^+__!6LA(tO7<1j=fSi53R9$-HT>wIcBiSPDeObGINI!)dNU?VnN6-PFmdW&`;j0 z*YP^TG8eogSRH%Vq%(lJ(RXkf$=|mLw;S>Bl)5RAIOgdVbm|8m(kl7aO zwfIdN7%PLh^k@+FyWI?=_vfj%Y)6UewLK=B(%PGd_N1#?MOebqQB&d#)clocyl;&! z52tAZ_JE~`?R1u$Df6xNnc)FU@1-B#w5EyDme!SuPcg89j%PacF5GjCH>6A#BHhph zz`K_d#tXfRLZBzMvb~-EA8l_QA4Pfpfj={|n?16*NFcMjL)asC2!sSMf|kh+3`v$i z2&f4`-2k;43hjaw1GW$Zl|yX~jvQPHDyXy=3AHL3#kQh7c7uG&m2Ve>tku%4+PWbL z+28w_O%U6DU$5Wqk6&J|$;>|U%yS=~=X1P2j=x->zbIz^NP7Q+v8A*p)(ZMZNQ7>> zRmXa)A&3#|q;vF{V@15W@i?A}_^8G=aG%AiTPcTM?{d1LT2%tQ)3&RI1Ywz1_si&C z6r!{T`#*%nA6=zp0Wo4IbO81!ng%_%nY9C1ps4j|jU=>2p)eh-@$>%iPEFhR5~hhX zm;?>hx*j_dTmk<4P-r7Gch#_SiwZs+wt}vT3TEQjKSV7Uz$MtF3clUfZ{>uo1RUsQ zRWSO7d9J4IA9l7;W0?e=bcvFRtDlaRE0u@sQ)v$0B9X(Ue5lg zR-9Iq-*nf|g@1+qJH*q|B-JI1v>OJ&jnN`qTU8ezdd5Y=3p=T;Cb5nl9%TuVq15>B z<5+)))sS~1^oX+JUk9&uF7zhCp?P6g7GRY5`U`K(v&dXO42zx9B(1L2`B3H0k1;l4 zSyCRo%i_7R@bcnx!7w!s9OLU9nq7LxTz}W^Ds$Lf(5j>e8BDMnV>TT6b@=|d&x6{T z1WOJY`ny4^@S!aRt-pRS=I~JH{Ed6(9m4ylhI{ZOjd5b|N>#m8({dwZ4KD+)Xt1x| zdZns_&=4La7qM4;)i>83E*MF3@2xZ!Drx@mh6MB)-L9y8hwWq+)9{X&YL{jUx>hyT zz9$ER$y0e*thZ}-nc01g=<`wg-f@&)qF6NV^6!{~$?9G7y%yj90^jRevjt{1O#wWU zLA%pds^0e{)-V-hSAR^-ANJc|R%u(t7^2!zBo9i)G_Xx%7i9b;DP`Pl`lWNQ-nyi! z#6fG(IYjH#(6^+@Tta^zh1LFHdo*^5-g5oEbdM_dQ5bfNL%LEuI0)b1`Nbi+KG!SA zH&MG@9iBHM_Uex%{bKgzb(?2Ux`&R1N{oXQxM&}4#(f8_S8>s47MV{6=N(RMKNc%o zCAzx!-FH+SaE{s?zn`SdsAFs_o_5H0d&WJsL{66Is?ot~n&KM9J!kSYJV^eYPZ~iP)l>4UJDb zCqbgnVKYqXCb7+sRN9HPgXfyHjiZkmU)43m`PHo-C2!}otqVlZG@xy`HYT5I`WQUO zxBP6os+sDc{{*DGrC0D3;R$p}Vjus2g~U(CS<9RD<>{V~#*S z6)VL0KDO;m^s&B`G*ONqt@GjmT9Q?LJ&+mDkrLfH4fB2efUbR-KyeG+MmW<*=Y^pa zHo^nyR<7+GI!+*|jX_+R#x!VD429NdSYW}?baDr9?zb{P+SxpCw^P;n zRb~C8D2$uNoB8-|MOf8dSi%&93szS~wHTpAb_3XHbdC9{l4|*bLi8>SEJMuu!XxRp zV3`@!vbs{$x^Yr?(v8rHoAmwcaC#(loD4qZN78!W=9Ivw*28u^_6DR`PFwYlHxq#6 zp6>yd$ER)kmmR8~O|-1l1pVJ1*P;bh$D4g|EtC%x*FrHUUhfM9;#(OzrRR1+3u@%# z`WKAlk@cRAT`$JzKXJuh1YZePDz3%!j^y9LWKQ$3DB&W}@Azlsl)C60 z`aQ&!TDPiLg(t>p^Za;@=CP+`?T%$~hNO9zNzM2Cvs|_3hb7v!A38Ob>m64+3_D|X zFu@J5U-*D(h1CbFotx zMs_m6l>TX;ku;$2&8SOcoOt@x?dtt>OsJX*itF#luLK$xMoirx9We`rRINXEeC4}+ zjO_H$5g=nFili{FU)`GO+&Jm0%CIulst4)&sYB}4dV5MS9Uu9XMx+UyL5#OKgJ=)$ zqXAk9!vOu?b0d1sVY}_NF>`#-uxGL-23~7)Ui1+pOhcgt%7Gf@VSw|8(Q^A(pzD~L zC1eNsU4#4a;c?K{X_!ashB?#ei42}dD5ACil4G9g#q0o}>QswQ^@0=SV zbklLrn_+Uz*lF#^I8895Kt&MCL;Pi<#q-RueAmM+_}&0rLw93pr+2XIp!3l1{`Ald z%h-5pKkT>UrA|`hd^fyga-Sqf*LEyP`?`Eqh@GV$$`g# z_0_P`sY1-68`(m$bBFTPbo4*no6q#u+ZvorWdC9^alLma)HC!fI9d+6)_OnoKVAB? zGodct^RyhH9&2RimNZ%f6KcO=fTOyo-lP7_NHJU3jIkVlg8oTVoM>~7d&f9m{M$)}5PK4{Js9z(pZ`yO*XR`O|OBxD^zKJR-0Ys#mUb&9rE zw(uyz{C#VjkCt4i{N=C~0!{0G`d(DxtwwuMnanE0`#t2DL%?CCZSpiExh&d^_?85i zv^4b8(V=@W3dZ7T%g{n6w5b)I)`9@lfXEh>;`>+eJ!sg0BBBwv#$xRtv|6~}uOM-% z_LVw|m3RzfiClZNwz34?hVb2e_^zQZY~@;L+~*M2?kmLTrZTG{C&?_uY4FNIUV?*d?MnFv0sq3|0g~|;;hI~9_xS?l?`!DW;!pg!Lhs#=`S3T)ho!h{FEPY| z>j!wQ#Z`=Fs#8SB0dZtLT|!theb>W~U*Wz2cZE-aJJnO5>+2pozlrDLxW9!v<)wJ> zd==M8{O&>;8*o?QcPs90{C))Y9k{Q-eG{%O(4Vj=niGRlenwrIC+0CG75wyv$HF!? z39a_R4XT+#%twm8;lmwN{zN%QL!suIeYfU*VP`a~Kfa}3=_!e#sXe89dzHW5L8)L$ zvkrwGz468yK8KtEhh)DXgZ!6co^Nvo~rhv~l!aW)aO}gp1RfqUaT`5V`VYViD1gt|z(g|oj zcazPF;oB^WmfUpH1r*1T{weI#BfkDte4EsXorf4vbN4KFwjC{VCPHpG*lTS z)LS+k6IswBklKy!7n~7M zfcBKf`D4sNexNhsVP}}kFn-Uy!A&th{FV7YPkk?$-No&O4%5Jjc`N4zs%ZbxljM!$ zH*{O0=$g$)??!Ehr;CmLWzH*=XObIr?NQNEQxs`>*p=^Mnja{sDy?$5D&I@yg4g<) zwno%>hoAVK^&i8?@K>^JTswXDXGkoV_Iu{h)L%=#)BO#3v5K~>9^5c$JwVGEK|T2r zvAdMmG%k(9?4xb>RkAcUQ79MZi!|=@RngoIIV#2_r%3wIr;^(o-@7#3TMwNIk>!F5 zZ!oPSYetW9+G~k!r70Oelg@lEL9wp#hS|2)?cU^zWDGyeb){SuHU8XUx?|B%ngd?C z(RD;waT&|&4zOP=kgcMxwmT+yX^A#rb^1Jfhl`e2D4r2`Xx4k@1!pAp-byZ*q~!nZ zC29c(Nlo^fzLAnd>iI^1v{R|`ia;#1IdsGAH>;mCaKB|5YXWaNK0YriE7b@t3x>cT zJj%layRRz=J7Ua|_7NnJPSb8#8jq1&13zM9PLyq?VM)PuK6 z#|pE9)p#$cpf$G9Kt!Kn&lAUFdVVmwbpj z9S1+bMS1vLt_Z&(G9FYyQ6;Ivm}r8RtIP?$6V4N5W_OnRL}{ZVzNfSFd@}WQulg5(c3SB()lsdW_5QLl#**dUEZ+o5RsF-&s+@yV>Bx@F~LcdPttK!%@Oiw9BK839hJJs{-P!zMPOl zdW-?Oe&q)45Plh$>D-HTXAMpjT(Bst4*G89IVY5=ppQpeg3c~3_!~%9e*@e8XvkW? zSqT0Mx~L2KGRpKjw+1px)4}IWbmh1PlBWrDbW)CQQXBB4T=_!MzC4VIp^)V!+w!_y z5AKVsD|1qp~Uhn8#82RQs z=<1EoD^xZHeBrq%_%6S0vS%#lyfjGCG>Hj|X zb4VQuP3v3c2;PztQGM}XXU-h#$7xp3y<;DH;uviaaHU%gWpE8cpc7xHN-Jije1X(w zWL)Phm3PB30G4r$*G*42^1Uxrk>J9ix5!_N?~;JAujXJC?ZxN#HfWNuEz#~K@}B8= zK4Ho8Rb0z^rUvpj-$b70=i|4bg>grIe~cK-OAb~UT1(xnIHNZfsOFP#{;tBmdsl+*v)SSM2;IT*VC#Y371UWr26Q0dhFCI@3- zGl1FnQIw<`Bcw?45~hNpp>gWXzb>My7EPP_Lt2roJ(ubHbTPaD=G=8I9a5|_mHTDY zKK1^uVXJ8O=#M^EOLt&q5_rA4S@`gKt|lD1GYlMso7#P5XT8~9u4|!dzWyk|TUrn3 zNcHO)t^^Q*Z|K+bJJ>c4=ob2D~fg+-8`hbF<$sKF1b`|70=gPs;#%u z_4NR#A**!0hK=an;7peZT`j^BG2BP7-(#U2vS?KscDX?x?B&ZI_~FDYCptoA{hS#c z(*zjJxoZ>}c|tvvWl`N$8bamNppzV5p=^D)bWYLQRtsyD8m-e**Qn8bq5%^6{CZOz zYsJ~i6VbndHi?Qr#f6A!k?!k6^uVtBa+p}|n8RS?ybsS!jD-Z>3D>7Dbx%d#FLf<- z*Qdd91W#9L57?{Wzvff)&4%!J=ZmfvT&Cqp`b)A(vXPrnSOBl$gTBn-bZ2FK4$ zUR>#V%7Sb+rr{~AnBS;fPHh}GDSC;mL~vFO$F$t?ejRBI0XB>YuE?{=?b8f?Vk}86 zO;{2M8C_DkwAGzhirL_szgE!#Th;20Q+_A76`il)Z>c^2tuw8=MkGqTwe+rn{ufD( zV#t`-I2H$58iqC<)kXV14341oB*iN=2-*}_Si`O$$IS}W?o3Fcfcpy@D;}Djzy~mb z9)V7e8MwsoPVJ3$^1!B6DZ2V9AXN7U=;`Z1ILc{;?3webfh-dabwei_cI6lg@%Wym zLFMe)P7UmicvqBDQ*88TurrwO+;4;KB`7)gSVKG&4@56qgg)bnJs#|o=e&Q+=I+k` zkGhFF3{6^CXpykPnJ$>zMRQ2D*;_QXs0>=5ugq?9^J`6PGw>Z@$p!mlAdBR=)|#f5 zX7cLbUU&zH3bK86H}<^(yK9jj@^;r0rAAtx3c3Zq2*b{zB)@dGosLC2Y=s1GUNObW z&&L19!Wm`R7|VKZ`aJ6E=bwzrjq4}4*5Rth^&~E7 z9m!GoHmyFj`jm^YORGJz^I%N`3-qJJ4J`oZ;M)3rxc2f|+d9&0aYKg?^mW!+i<@mD z!E2bQOi&A}nLGu9j86}T{v5WfEf6Frrc7)7g0H%l1hqp4l#r3%WXQEvYn7#=##+3+ zaZ?2gm#B|{)*hzgnA#pBq1>9zP3s_EXd*dr-Zo9t*?)W;ziE+ULD8wzt4~DvFKAR} zPr2JTRm6^>m7-Z63~Pqx0rc_(;wHgQP(A|OsV?v^JW3ek_rVWfbrb9Rt0HmvJRGK; zyrnFaE|#vXSHe>ux-^UT z8dvew)>X;Ys#T12(dzT7OlVD77oxkH95WFM^I>DHtU!l+a^z=iZg~$MH zA@W5tzMxp*6tQ5F3!JJnZGlRd<>Fj?o{~TIaf{$WF6Bd@aca^ZdEpUYbU#8-of^;w zp3WGG7gY-xX`iK*Ky#B%xBQIutoByVns2&(_H9olfwKgB>L(dO`>+u0jnd-F1@QM_ zK{~%s(kToV!iNAS97bu39-4pp5Mw|1NIcN>iH#E;e}ujP`gyIfj^e&4{sd|{E1`bK z(#HDJ1s5c`1o&SRr#nwbLk_y3_u#)5TBnE&doLySlrWbT<%h(3BGBlSknx!L@c#i@ z@Nnp~vhvaTk>DnLwH9#*B<2JogFZFlX`B-F6rN1C-i}t@-W-ag$iWTGv4XK~lB@FC zp>@y>8`Q(IEduSkw{Fh!)09>K(FS*5w3FcF;qL;tli)I>d^hMu+6ISi(l&T?GF@#7 zye+dQ`GL)Y_qj^W^WX=A*48zJ*7Cs3u$5{i)90sezSlw1N(vu%B-zg^@Auz~Any9DuoW9b}g`_E#^v+Y@@OI{RLx)h8@7z zrSTwpQR4ZPc=Y%8l;6}24R~bp#=uI10AX=-$(Uji{QmI0X83;p@V)Bh=rS&yf%mSY z5(2bt=-KSD3-D89OF)WW4v}3zGuScCmST^^@4pU(P98$~uxE2%KX)9a&+)|ZD!nHW z2Q3@cJqMj%$LX^`9JGA2Ou!j{7X1^)*rq#5$E2O%@4t@$)<&(c)El2$<1KI&%rSy% zInFoJmJe&N^8=Gg;%y)OV3M=TT0$0;zXy$p%F1y1F{!fLs(ZCuVW$0v3r(+ z3Se^J2LXE-*5iz&wcitdA%dEy0e#UzfWJJplxuy3w3cgf$t998K-jkHrlUlaZ95k) zyi1tib74*!Gb)*ka;j}%{;k?kKvz-OHsC47A5;1+?wn2QkA{^qeaitgkWt>gERGh& zN+)Yha3`XBU6fjmteI~_+Ch99cNNur#x+6%QRD=zljq0SPu;sn(8GS5YMHf(jaWao zMz^}EY8$1h8qe$zyDty$kF;e>dQR<&Vu1tLL(b)&v}lbhXlXuC&8!s82BTL_8ZEcar_IGQXfHk@_C1< zo48d4@h-Tu3^X|Yirk_~n;qA>iA{Ct22uuZE*iD~pD|<$?pLjJERx^@uuuh`H#iTv zOQ2ICy2r>9&u&VysPG)>Oe#y7bHtrgyu{79E12%M3BcFiEFW|K%*`~cWL)y~IFx5c zyTnPwB@0~JYqhC%X?u-4M|SRce9tzE)be<|aKXI;9x0_#CN;^ERCf(~pEze(-7$a@S+NNiOWT@S#cRTSF8^1Z-O= zZO^E|XHbWKrqUx!!;vsJx*Vuovf>h(2f8!WRS$!addQ=QV}i5a%Ddw`w_@&Hzd7E? z6t+0Vp38COlvcXpmv>nSOZ2)Z*ikGYsT$iJm&ujx9JHF2<7~0SxO~vo#6+GB*t%Kz zMEpb8t1;Ur6W|3UjqmfB=PXrf*?-aKTv~5*E?VEMW3v09@!USx$4c&gSX!K#DF z>i2fxoB=$mng$OEPUwq#H*hfq9F9fxG0qEXBVQKT7Ad$Xv@TTjY-H>yXB^Z&MMS+( zH!Hmt69>?=yzKd{rVmBNKi{-Pq+^V9CY8=#pD56LZ+MwPRc7KjV{Lq?UNqG#s*AI3 zlbB%jO-`*t`++Ou$4={~C!R$fy+5HgXg8~)rNo*Ah`C*2t?AXyaV#gbNIk)OV&uZInR*Tecz?*ifjd6#S-e26A#*uTFxjTk0~J!C#l6O%jcGm3 zRA&vP<=g8!s@CgA-qx|H&q)cMNdF9Ay)n9@Fh{8m;rNrZ9clgOS~wZ)UP#X`oqQ_A z!!DPyv5Jy)Vh58q2gv88=d?H}G0>HVS1juispZ}_{uE;?u5g?AR$iRMTHrn1+9+1J zrugYwb4eRt;XcJwD{rH2y=|>Y^Us$S-J4ik#XH^IOalKQFXlz1sywg>6pLN4B^7+R zD^ZD4#p|6Vh||q4;Kc$Sb+Jgihp$tm9>ATkZx@@DbGWjW14ktumx7#A8thEuwW-2= z%;a(2$M21w+s)kXW>OoBcHv3)D`E=#*Tf2sro2-m8Yhcl-U~!kr%FFAjh9p&0`F34 zlwpC3^|N!EjLkJc1%Hm*mcF)BYfS{b&rH%Gb$IuHZ~JO@{PJ@m1H>1snON~g%EZH} ztgkb-Oq=>LpL8E5ED_4R#h{1{nRCuD!K6V=%J82ae}wY1M86J_AD&9a{d&j-c~~BY zLj_^GA4q-h2?9Sn_?;7mKVRDd>2tL57xyxjBta$KqrC`&-30HbIcDSi#=I#L>I_Vr zb&_b6+W6BQSspPzv5tp-c=#Uk>*mH~v=7H>Og3h?EN%C zD~G|Wqgt}zP%xayQ{DS#;29tqKD3zzgJALi*Ycb`eWjc;h4M(5;GdvD_9q}-LRS#F zV9?s0$ehc&gZS^bBiu33!`w~Ae~z6j9E$6sTqRg;qpV|6R6fpqx`UQulwY461HWPV z3%O{yW8qqd23#ka|NG%CBZpnC8@3Z~Q;&J5!Cye<5i+vR-i0~Ag7T?wL~MTO@A%S0 zca(G1$<{lzn^OhL3LErUg=pRtGz&un&uw8Cp5XT`jcc#OAe@wabh*s))W zG>+t`1j;t-lw6+Kp-%0q>2)gi-jodYij)_M{?^f?QM;!}8Bx=uY!~a+q-BZa?oNz0 z;$6&TNsMHW7P>+w^U(8MFqJ&YjZ$ZeHmNK15UW$sz0T<3+>6|>jdJCk6%M4mMhSg})`))3SXlV-GCmQZMNoqDXEfL2CW(T3rADX8lB_79$~~WO zpu-pRGlg9pmWLI(5Bux?_wv#@Y*Xs@Z5?>GNN8DcB1CyUK~370SLiF)1gUii4WV^2 zu4ils@aY8$dw1j+WnRBko8Sm}Tb6gJyJBc<{@=77=e|&j6hB$CJrDa(Jl*9svF2LTk4iAKB4|Azw-3C!pTIEhv>BZ|&Hfd$t zB9}Us^Nr+?cQOnDrGz9%oI9`c4;@w8xm2CbDl%CrZ`F34&LFbm|LLn*ep-K;&6286 zf65P!>|rr}9<3m1<3+8{xSrO$%H3saQcA`7tG6?jc5RD9M^R>h(Zjmq*V9#(^UdFm z5#;6k72A2CN!uXNmZC9`w#Br5zJ@zH@~tv5++9&(oT_kS)PHv@(G+Q{%I#fIBjc-n zc%)TsC&N!BcQ+_FHIP{&y_bnSDl*<|u#;_eBzUc$?i0M0+y0MJp6UNQU##6|i}CC1 zNjAM-Zy#;b_@nJ(Y%0IOo@`_MF?QZ|sbh2rtuMtP)4Hm8&eBEE`NjJy{lF#LEWRL( z7rN4(P*BM#%fW|bOcJH57S&ZizB6z!?j z47OwmeauZ&j}d8K=c?@P?@3JSXmN_9v5j@<;TO^F-l~j&5V%8hg$I6;Qr<_0?CvC- zOf}A0!n>K^Px?~bjugK;Y&VH5QoQ6>u#sr~Gc2CjI;Tk(%rAF0x=q3soYukx)!+)k zyB}6d4qg%m3)zXb-4_kU~m|A z4uD(t1Y;j7zACRikx)vkG>vNaM#m^G^s6R6w2n-O@vW49y!Zj(&kMiq7$Xc$J>h;G zek_^vhgLI_J`W7$FK{iD75%#tMamhM=3Usy!%v$XX)SWMyW1SGK0EaIX<2nXD3yWY zyrS4_=YXSju@-*vZpGBxiW#Yu-cR4PxeqLEbB8B0`Q06D(7#x^y6_~;2j@$LV+6mf zCk<#DcurkMvg2XlKA1n>-Q;d`sC=b1pt@PY`CAqa7F41%U8b%M#t(@+iL?_bCq;#w ziGmjXf4ysCfMluQjv`%XH355{o?aRIQl%fZpdUaV)Nv(j0q1epSa45H;jB0l;lHv_ z`je@HH_19;c`i%qvt~~Of0!@P*a&dq8B3<$nw9ReWUGPFp#cwt1Y7%6ejCc$Ru|{I zuqxKM3u{<6frf(b(pttYhz4K31(-{~C$MMhd>884>qfCAAUk63@rOgB29e`QnlCMv zh>Na!@t^|c_x%(4;3T!hp*gQ|>MfVnE=}1}bQN^MPoeu5f0D*$o#&7TT`9U``dbZ- z^&(e4{D-!=xKb_7!Ca{cyap-@@PqcD`FJ|t?=Y4uU_R#ex%slL)CuAtb-J|AHD+!- zqjTr++Wbma1yjCQ16~Z1o+p(r+*dnA953yuiJP;yrhKsnv~N7<;PQog+|k9`c#Bw{ zx{Slw+126}t@Y9MT#IYLTAW>0VfR9QIJ^A(pDDzWHx|z`NRZAQ?eDRJ)T!yI!&9$d z)Kn1aO)baWR_DY1uy{$~$wX%mGLTko5!=q3j_r=EjvEKvFtv3Yq+nxh8fc4hc9r{C zCgT}>$+)yT#YvL&3C5i*8lHJovPt?UShtaje+CxTBF#)yzEG33I3sB>X zbvPM%Om!~ojwX))+xHP{19LI3wZo=4bbWd#vdTa@vH__?zECM&n6?_|8E@lz)`Zfn zq`Z>gTwPvX4>{L}qz+zmJ)m#V{%@l%=vlTB^z>c0s&LWuH%cVrk@pFqeWk3)btE$$ zl1IjBcAK`+)J@y9G`CHr?MkkjI7Kc(#~l6U1MrCAoNcvD(M?=ijoA$zT7hYG%UW2^ zI9RD|m1$iA=nAb9^7eHbZ1G|vXtmbWt?TG}tkvM!N7A8lIKDG_tpQy3XrC7Ko(8V7 z%BQ=PHe-qQli(5fMIgZ)(0~5M$KHAuuZ%Tt?X$=DKI)iMyns2y@2$<7vz4I;4oB5= z{7#so&9C9BYAAQgx7Y)_deJh|&t|9kKI}*Hx{0QhQgL|MBb;T`wGJ_j6Q+P-we(z!$DP-Ol9>nfFU3A>?#6Xmsn+ssT3hcJT&s(7&qth? zwNs>+RrG1=+Onwrv-Iio+COOe&#H_E+@MKL(()_yQPu#1GYOd4n0p0_){2xiTtzL7 zPlXQv>l&OM`$6E3sY=@xe-2NzeW+EWtTc`I&eI)+;u1#U(dw!u!;Eb0`6QvuE#7rV z)f9cm(8Sp!)<4oCMW`2*NJYL6bqYeNQ-hpiah4=GcY9BFSj(IYY5Zb1wdWmd_a65l z)ggmXL9gTC@njk7hzfBk42RweleR4Peay#3lzSaV`8gy(v~B1drFEp`Ob2#` z*$vrMjs&ENi_9L!jB_TGX$U$v7L*AzrH3?-@%i4glo`3?yqLzcnddb#VZIP&)@+m{ zrH^UhOHOqxVz%-3)il)pQdJ-QuA!bQlp1PGg3hhYufQAD;$3y0G8PM^@>M1w6574C zLDP4Zv@J7N7)jF_<3|B#D=Hv8-lWtrl{}L~(n~_S)xF?a@t!b}kW|S9-n~NrR5TCT^l`|Q&nQx zLNV^OCvPuDu+vid)G^qxr;|qZNTLV0-Mhk}HwL*^bs5xhEaFGO8D{NEfvx`Os(!nD zHMT$7MdQ+XrhUmO`>Oa-0v)L_p0|KrMl}bhU-@O>1jsHR8}aC!R(Q$F6jJJGx|NW@ zu}8w8ErS#<@wG5xp_aF|w~eRsk9AK1Tf-o*Kq@`G#SZDzQOM9LQ#KWy>$n@M?N_i@ zfd+>{>77b8o6g1M`m91MpBAX|-s zbu*<`%vTwr#g&W8fa_t%bc^c@LUiV1=Sc8)zgAe6x$b*X)NJPuR};%>zpjpXnexyQ zJo7!7g3b?pKhFZsWN1q;pcxVo2AgPmg?}3?)|qVhGyqo80#B~)>dJ5d?!+pT+WdOZ zk7uHC&`0oXeDnFbF(qT1*%p&a?+)iBE#~ZdBsOill(ewaLVxd(Kq=zaHf0yxRuk(t zl+u(K$OY#QX;4<^;keYdb~^^X&&Fe1ccOjh{G;>n4cwVh7V$tqVlSoP;C*Fje2LEX z740gEcNBWpe?#zdS>Qf8J8Wh*#TUjN=D?1;khQvP20xQ!@M)Y)|M4ypT&329l!vCI z3wpAzvluI>08BpO-RhUiGTocD8#OU!DaG;!P;&7WO3OE{W2DB_GfIUFp5!Kf)G3Y7cs1oi8f$Y`o31IJMu;hmn&{gM6|p}~}W9Q_lK1us@)x^$c~p!_M{ zGSNm)Q_#%;olI(nLPu~$P0E9xr6J%zI?g@jk#TqIwBq z1??+lipSNg!yTTinu%QkG8@%Z&^hA-Z2{+^sj)+(%`Pl1$f#-aFl{NG`#l!nf`_j6 zg_w6E<#_^B8IT>3e!~!h6^niugsgig^fSCsD{p=ZsrOK51xg&WYXz{^6)uNoHY6O3 z5q8$?q!qYdUCKQQyIVC;TUzNVYhnGcFY`yCE#mA(aBCoAxzp)z7O|Et6J2SM2J{)8 zIL0+DhUNmF!PiZPmV|k(*7`O0;iI8(_|%|XxF38Ft#!8ajd9hzu+JUDE-i5Fv`imT z{Rs5Wo49L~r;qUzr92%8Lpt72K=mi!3+EkRU_Mx2tYfB|>gboFMF;J$U~8@be`+6KGwSb&OZ1`!o$Yq0~&c}MaTc&rClatRYX3KQb&2Yi&zIFQA>FiB(yJ3H#VHds)+YIWcMh*wyvm^KftZ2T?6SBs^kvvK8QTpyXc|!J1!@iRz z37Toxck(2`1R8c*o+M|qk7Or8QbK%mm5H=lkrp1(t-2`asiEhY;hw)d1o`uEcr5Q^ zp##F+fEO5OS<(QXXW;p#9PD|lJM49y zGhFAF%8R8^X{u_f;W?hD>H+o}gan2_uPWAQ08feX2v(vURnYy0zp&sx1`AJWpg9rw z_0A18*gHsl;dJp|VTNN~D1UyOX9@5!!Xer(9KNOU=lGK}rk^Ll%sy(RK&<7C)*@&w z-^!2DW8qM;k{_k(2Y;XGp z$T0ZkP9cK()7L4nGs$n_=7NEk8k;S&>qzYBxD&c(9QS%{CeX5%Hu<5=27f%n`(uBl zM&*sOnM74K@u~`{m^;qm%s!s@e&%mys`dVkY@wR{KwYWthBLf)sqbWX{55aA^|UHh zGG~*XjLSf>u=vEsO}oU^DZ7edrFL^A^U2wEX1|Ui>gU{ajN2{la4fo%WFBWXo2Lo; z#Tsa}eWrzL{i@gT-4HB!sAswlCzek%|%PqY_UFG9}y>H{QutZxYrS()szp8e)^OxoFyDMok>XQ{A-*f$35cOEiL z7gq#Gmh7t$KI~vJvwOl>Y2L5-YOO(V1<3eBF9fyT`qZnc3WptSQr5%Rzc$hST^E2w zyZ15p1His&-x(k|)4kmi$^Hkv_}m9C@u@Mw47{Z|%|S|wQ2$5ay@~iH2ilF50N>3E z+zoA?L~%UcV*SaPh(7x>XhC2IAjFE01>VyVtYnd*(`(L}hrHX3@GXtJY>4Ys;)YWV zfdY(P*!~0r!IJig__C>4T$IvWWS5Qv!oXIhr7uD0dz2RXS8toSoSA&~YqZ2adc&!- zL|^pQ+b(LmxkS)H-)P5xM^8%uJipZc?Ik%e-bk!-w_<&%#QHm8{SA4CQ$OydCHSxx z`Dgqd{kC1KO4*M5U&7myy@@Hr`)2R*0F!RQ)zeGmY2krj=Y#USa+y3+4jz};S&$Gu zaV$<)qtA`4my5jN+;o&XRYk1n(l=zo-CO1D@{PEkvUOycp2U*IZSq}cmC2yt%<#lc z>{rQ#LeQ7{C7Ee^Oe~T2$O%$h7CFDlzh>T6vZ3-_nN0YePitfCjdHtuKCnohEW9r> zO-w7BbqDot@B0(ZAjJEMe}Nn=qEFNFarQDoSDdkJm7C?RfK8w_5^O%x^l^a6V0M%7 zzw-hMD|lo;8n;JW0}dCl@+PM7?Eqaz_6@8_lg8~6S2~D2*VKwU_XiAi&f1E4v;{r^ zW$*)ex)?@2YuIkJM}JWhFY%K4*j;Zo$gT48@+&e>cG8Lc8!l|SPRCgK=K;(RF3K_8 zt8(1wixSeMHS8KaX%E|a0+}YRVGXm4dC_s_nW<)zjj=Ppd8#IBK%p=fk2{!iQ_Y-2 z=gQZYev0GS8M=z05VvhZ7+$gMx@G$8OQ>;Bpvm@H;0c}FY5BS2_-$3R? za_RqO_}zHb@ulxshuTYWu4AX1nR1{A{(3Bd08KOaU(%d}G$$kW7@y1GD%vcQ>?C-g zupo_OU$bNMCDp}O9iz?>3;uU|9G)UjEOuTpfWLa(w?qE1~$OO#e2{vVpLN8vz9R1$oa=m<~-~@WZ>9`GgbL@6`x;LDId2Ab{ zN(TDkhUvt*NM0^7O%<|UipySlZe4K`@bz|svYnyK-zK?5?g=nEMVZaa_AzZt+GsIs zC#lQWi)xqtx`vlBCGI=(h>Xtw-alh|TyDTTzEdboX)IzVVHR7-#1Fl6AN$=6Y21Eg z4x3HH`c8lYp42b=Oy)dj*Er;O@i!d=IsAdnU`rcnuoveaHu&m|HR;OS#~hz(YD2ji z1NEsS?J88pe-)^f@4|_9i~MrnE@6xOQXtKcs+wjmvLebXOH_kc3g z1C#JIc|WBMf&F!q*QrcE@T=f=FlIwd%F{(nvDf(|=_oT^veOx2TdIZLlelrFAUWj? z1@NNL<5K34Ewax~wqX|MIt9@w*B1=sB=<1wOxjqHq=xN3R8|octP(Vk0jq?&q-E?f z{rz&-{y;#bJcsR70j34>J8hXBmTqDNW^}cqRBkt!bJVv|B6eAs%})9D+5BB-|i|T5+4Ba+uoL3Tnp;>rCQ(6Q~`=M(Le=@!#p4s|vjnqtH9KmvKs0 z=$)P7@|2xLF;X??oin%So!9#!^p5NQq<2mRz%>QMlP^Xnp7pm;JntzKj|_?@9rVdz zh2l{w6wg1vzl%^j&xo}t&lIVpYEV48mC`TvK71R+^9ROF?O$KabEph~>K#>q{lp-x2F?$UB_+K`$-Ad;f*@$q`N{w9o65 z_DLI!>(9fqkHl7Cr+Pom97`1Yc#i*!z3?8p})YhpLn z#CXYbvNcEFqqdDQSp}b{7Z|}jDKgqdOKO~&9piS2V}LuqTvt?stcM#_qk{+Dt-Ez(smX}Fv_#H3Q2SVPNcHHa$kfmQkQ8U1iM$9Q)r z<@_JmEsKx~@pO4)iHB=}b_i!Q%$5jQlaK zMn5yoDt$nBu3oMrV$9?6xwy@;D2w_9ah&8OD`V~uHpvz8L$io)um6{@(X(*Ui;XCjzdMu96F;QXj$?}o&S%{%vl5>Iy%Oz{!N)(s!&&G$BLt+m1LzhtjQAYl)j}G`%b=9{DkATXn&&O zq{4}$=WqUT_;0yvv2>YD!bbUVu~P06S!st{DVNF(q9diDXh2*dv(h->dD9N1Y^TjS zbCM9vK7Y1^ou{XmT_5=26AgH4te~9+9f+P^`7^CLs3hzbKNL064sj>28IJhxG1m&v zlju3;A7{JAJRPUsSHzFRSHtMpjdNNyIg%*OY5hSo&~N#u~)}M zM{fzdY}x@@id<^(mxDf9;C%|UA-)H&U(xz3kqeRcO+PJx^RmU}lH*M#;c@YCxe>Kl zB74PB)T05<6~i@i;I~UYC5|#auhguH*BO(PcAp&ZIGHIxbnvBK{;|`Ab_WKWD4;wa zYXqr8n;M7~>=N<)?lMjnIIWsFb97;VnL#El^Hs{Wk(M&imZ}X@%IImI9xH2wW5-NN z+Y#??{FO3md>^aiYM)yW)nW{jNiO}bf00bv`Q4%qO&c7)GZ$hEY(ZF(`QWUkqAF8` zI~bf?(Un;~QtK84-81XKqTTy@iuSBUeANuuWwNUt(17}bEs z^1B6xx*~=_8$RnVETg`WUiaTGXWv%;-)kzgNvNS(=;)nD+t>Sf?@_E@NmduiZXc^ys0ny-zur zG^1$jjeK<{ID{*GRk9IZz=^uB7-f#`RYUUqO28#Y+R24cX+g@b_(iO@IE@eYmJ@ek z@9bSgTgv;R0R5WQ`HO2LH^oP5@v!$SO19Fsc;;d{Cin`+R{kFOU@yrm8P0RpaGtI* z?=^!&*Tt(HpqT@Uk>*10J&t-?Job^oT+;J|e;oer^jmD@W<4yT9v3abXPEyDm@hj- z+P@AtN&2f8$?Id})r!1Uq7`UsJa?^9&M>|0Xu@c%aMYVvcKO*#SUZi3)vXw-KSvy1 zn(C#qS|!z6PHPFrfVS+>sv#$?l0VWe)+E8V%tP|hxYNXl6F@=PBiHgvn`ZsO7peP? zu93_;yfl?WZ+#j~=d?B#`$v}Jn)jSG({aUjzx=t93L{)nR`iFj*~%7NBld;BrX#j5 zd+!!3ck6}EVKHZ!ILRxfhs?hgBkeLCqxX-!V@gTJXrZU~+qQaAY4`ZDylb=!xz{+1 zw{u=bxJ$^mX2F?DH0m+d8)Qpvv{$suG9MXEZp%tQRe^lRO0r>y2`C%!hGfgfB2CU-h7-px-yBJ!t3qeU%$|W2ltwviWNR_4A<#zr{f?c9b zB`p`Zra1VJKk8pF_Yj#}^%C|dmGmPYWX@^Y)GhK>ncdkPAbZ%BQ*w#S>|isO!FM7? z=oPF?-oh(P8*&y&+Hh1Wuw8r$(g&*(=P}E(=;^nR4r2k2&%&gsQtRc7 zsL%2MheH*+^PvE78x5g+G zgEyr4?g`NbUK7_Svt^gzE1kANkFvfnur>P(XOb8NMJ%rV9{IXSwe#F8a(=;O;+uO} zwTGlJcg>YmJ7&vAu=jARAy$xdY?{HYG8;%^A-MKT^HAueex`MkTqG3=+vF_B3P0^H zFz8f9Y1=Hr`D$5bWTrn2{iE5Jx6LBwW?p8olQhrN85hVOn|P$qA`gY0?AJiwBul81 z9!Jj(h2HO^@|*G~LmcE24f1?>oitA>Lb>jhJ<^|yV+`*YU!!Nxj16p;agt$_YAR4uMg9c8 z$w9h506yJ2exs>ae$xEftapnxIR0dQ342T;&P)_1dY~QqmF+6 zYe=ET&(4@?WcQZHYfM?HJEdsVeX`zQHi+^pxe{mU$E0=A7re%B(YTk^C~YNMVH|59 zDl-uFD~x7-mt)Eq;v4kC218QqYn}HmBld$!&-sfLdMz5~ehIBm4F_-t)a5;DpTSlY~}rJ4W}G-aPE?kKeH5t?td7Zbc}u zZNbc%-%EG>H3*;HORT8-nY#mI|04Ol0!VKd8&rI9nNa+SP-udi)2cdD7|9SgS(;j>c?(VdZn6A5KQdkvm>p~AP=^e>}Qe7uV-#Y>(IW_ z89(L^^^(0?QfkQ&$I+sdj`7gsB8}5L5g1ph+H=1=%6wML7A!gAyu#cE z<%7ok;&j0%Ia6AT60mE(9ay9}t<_81{zkc)Wo$z9G_04Wug#tH!MSGi-)iK&-*Ng3 zBgA2!x)Pw{;6XXkdQ96^nJat!8pYNE!7?;N_YGVu)|C_$Ay)>%;qT#oJ1>n&r0V6* z;x@`W7srw48PS`LZI;c&WOoU9fczy6K<4tAn78DO&}bN4{G=lue9qS#qrLye``XV~ zGNga{Vi4o+J{M?W@IJHu2Hxjuj=w@faOtdGpLf<(-}zZl@Z{+C2~vaydJ!w_d1Vc} zy-a_I``@@%<*{6D^lS1RbK|%<9aFqye5|ifDsmJR zX@TV#jkJxv-_OeReqVMgJWn24bl*TrsR~@a1wj0O1`XsL*S$;SO65He4S>w6_La)z z@N634p?-VT37-6(5G9>fIHX?(9>8w%TW??BRfpzM^o1JvTR!Twz(aC`$LbF}I7@#n z7Cg}hXIxCqDdT4tx8Hc3!>xqfYCntq?eYC4@B^8(BunRfrvk4zR6VraXq~+H zrMXC2T(hp8(|gH&V)?W1t8Zh&d4n059XC;&^vtS`^}ik^irHvf~RX&a_# z>W66>ws|A=bGNtF$-?VTKB$@nplVD&qFowilA7dYrGB!Nua{YP5+Z34s-}(%#N`WO z4A)G2kN6h>1F{z1RVmca!wNNYud`W(Je$DAuXV1x3MWTO*BtTBAEs*-$T*dFpYoHm zm*vB~y@9mt(~19VGRLOzZ~~Y9Ni%#|Y}&=uv9XnJp!X zc2EOzq(HKQ(xp_@+{+~R%n+r297r$D#6ojcJFQy2AvTL~3jNaz z`o|=Uaq=c&Ul#ycJ@%JY`G6ej+#R8YY>fR!ph8ut+vF`WlQu74NafNXXH2U{ty8(f zGUt3eZ~>*_TE_}M9_~|0&tzVsG83Gc@XYQXV<_ZR4Wg{U-bk?Hk1}w=0$|16E&K$# zXp1~ucvxCyJOt{NZMGYh&fM!zooDyL@`BAZvOC8bxSgPiv8$#U1fzP#V%cs`3zbqT zegn@^a7o{n9>k9G`k4g^d*Ya#oEsZnZlzlU0sg!;T?)V9Qo;=NPf}f_sThK8y_79}{rI}Kt^nD}K zP-w{I9W&pMUqwlo7OHE}#RCy!4-1qy*UT=XYu2Hn+43^SAvs5N7aUxs8s^MAAfKCA z&%ZBUnc0Bz&V6!)qf!3KctzP?ohaWqJbl7%a4eO_Nx6m%#ty`qGwWzkg=3{-w8ZTD znei3lm6&Q)y+2WMu+yYAnV!v0#l#Cd_)He5UM`orn3%J(WX5){4D^3(wrKi)*n1PG zrmn3I{M-yAVGN2I$OSG0WY#c>IE4gK1`+E}2dXAQFj1xwP;6Du+E!}^1P4ZKwS%qg zd)C&zwy%SoYsa8%9}c`mZKdz^^(!550QvvUO#;~ZzVBP>t?$3qfBh4<$-U>EVV`~W z-e;eE&e=!zvxG?r(yf(>b~WmcLa!(;{5g=s8GB$|l6Ya(K1)yS`5rc{UX-NGZUDb- z$!f%S@q1_@OY)J={st~YbDSL2PgC565dvn;FJa4$|7hetW!hD$uGY&N)rix8=45gSf~)kb(b0U;TSq;b)_4g@5;J(7yn^YcW|1J7Kc!OL8Kw+~*a&#^-r` zBXs8P?3mY_SgqNmUj>WFqxQ+X-B5a-L{Ec-38Qb@w|2w7u^dvH#CrQNr{z#~{&}b6 zP^8Nh%o8(FbM@4E2oG^LSPu{XkJiISU?q8Hl=ZNWx7C%(D6>%o}cMaCD##G(JinxcjB8ITqTFdq%z!PCu3~ps6W`!1dl&S~C6^ts6zecKtj{?DJ7SY^#EwX1+Mh2~ z7mz5d|LU!xSh7{|RxJwUc~}!U-kMm;TN5j9uqKMxR#+2Ld23>ijatAi=vNfHKgyQ4 zq8Ix^pffB*z7C7xcu^v6QQXX16nDa+cpEH=FX)frjOhP@RB%`nOG93`iA7P&8i5Oi zZub9ZCA=_fC7f1J&s!Er*InN%*FUKou|j$XX8+C#c|mXaW^!Jm)?rZ;vnydyOuMN? z@iX3{`0*%<;(KU85@Go!wBQz46bpHa;?KNA(HHef1)V1R!J=pzWl6lB$9W8INAxX- z?YyB`os1bVTymK@`q0wGFUU~C^zSJbKbG399Q;yY?()@2RPbkTMOLIc; z5L)HO-s|YYf-$a4#x)if#-8=xW2}k2?;(k{_nq^Hr01xtXG(nFUyhcA}tB>?yKQ)bXW(pl+6^JJX&>Zw&%NkOzeanJ9a3S zNMv3u3dB~0_=K}5VsD)?7c(@{Fb$*2CAre?C0=ZtPR<6>^{I4Sa6F53UKkEt_KXfX z=Y_d175kAUkfo4xXngWzLPd~9Ec4R%e2)1~p^fG*&H1!fl0(8i!YCRmrh6IIYw80U ztf-B+gn3ZEhV4|h;Kx|`#7C(0EAlD#9H(2#&J%y^_a32hI8i-Q3(o{zj}1CUVpDq> znC}VQ^%bpK>!;S~=**`|=vc9(rmHm>O_YsE8j20J-Hlb9T}QDiC5)&R3r>hNo?lC( zI!=c*MsXfpsXBjHgbAm^`pX}BC+WUJfB!vc5Jl^T!cX$7|}T0iJ;IJpL1jKrm*c;9lT%D0&59fb%=4aMy(^^ zhkLyXvCcB+DlEEOjLas>Yf(^t4Qib}ZVzdD}{k;tshwKABw%~UYeh=W6#SSE; zs0FL`iMM>J(v!dQlulL3_&b?ss^Eb9c8#Ly7WiKi3Iq&3#QEtvMlJDl+}`&Biya$S z(|zWw9lj>RJYapL?TR(>XHM9eJ*06v)dOR0?SdEj?mMuP=WVQgmf1K}wmuQF>Gx>v z)0~EN+fR2d`j>IuV`0;!w$66_K>zDQMS2~^N%XlD&sT?%y`>_BZZj;EnyliG2H1$} z&TobVuJ*iOx+W`EpBc0rE8An(f&NE^mg==S3GQ>SvTy)Cuw8b}=d&fJ^;vg?9LW}R z3uZl!)S+yIC`v~ng!Y%U{-;6VQS&ga0wu)?ZPQSv#o9+RZ(KDf#p>Y|Ln5rXe8c{7 zHaV$1&vcSj3HzY-mP~suT}uuNP}o5KvY`f8l85?pQRjJGnb5_(MAMZ@?}K_DZ_>;} z#ITD2Tiy`azgd3^=5XlKeW)e1TR*Iop3c{2W--&Y0n&$IcMLk;sz0IJ;jH20A<`a$ z{V@`xBFzI>hn^-Poeo>>G58f2spBzVK9tSX`--OMcJ|KGpVSGl3cU&TG+HyPjE&N3 zAI_wf!~6AIFNakFT74?!eW$ZM7&+XhiDSokPXl!KVs48xPY^W%%D(Hfycw*n+Kjc9 zbfx?Nd`6KDnMmawsM`T+vLN|2F-F+}IW|_uG*9-9L%vgCi4Xu=jn@Tjn?WJ;nbOC{*BM$e zU#=&h&&7PfgW6@?JF<&T3$Qk;H7hr8ss8>TIaZqsn+E!;t_#{5K%IDMp|tvpBfS%H z&(k_*4(Z4tjnAP4IV{r`C=X+9h;;giv^Z}u7Pf$Cq6FB~)4l!KB^Zyd(V2Cp6h7WX zfe+~0oNLt@6v5t_z`L`(PYG=#;s{p3Y`j5fg(F?GmUf2|heYtmIhK0l}>3UjgIV}f` ze~+E`p5RqwP$GL;a}O{X2R_}ZY1Kckcg(*~{%S$}za7-;C9ED)l7pwn>r3?xY(Auw zot9x%fzG`wI{y$TaRFvdWP#h2E>8VuPzOAE@SI9>k|6C^%t=rh*p@9tYAc^Q?Yv+n zXrVjle7Xp-FKQ}#BTq7I&DxdS3P9a7C<-xjG41;?qY{5!uwRJt?+lqF>Kka^F3xPk z{sFp^YXfRXY%kkYq6F~eQ~HVCEzs)|`C4omr1LgnNVFVK(?I_#gG=>N(1=2}1u}#L zt_j(y6?AU_eag=Vv-9DmM3o&a4#mUJJsw_=n@={bg_^e^Sp#lRZASWolG;?s=-ZN^{* z%>(r8N_nrnMZX9$O0Up4&izu*v0OI;@r1AwDZK@d-b;q(hWs!$^njk99m0IqNz4w- z3v9|>aq2c3i3;KCm&i^=ZNB1ZYb)jt@6|BP&+Ap9iIgXRO-d233~0frVmzg@JMsM6 z0JcVmrhz`Tqa9>uhX=F;-P^PCPYY(q0`vG?UG^q(H!xtymh zM_Njm2}m1vno?yxWJ?0qOuky;R!G<)2&eJR9>cI5`BTqzh({z<*(F8uod@zfL#yhSEFFaGYbr zd$n`iuf#pw>*Jg6TRhl zr+!lzoJ&eQz0y6t3WQi7B!l^lS!W;A&N#*8v+%ft9y?~N zO={LDeLnY!6P)%ke5?qexpx(t#~Om{Ic9^wn;mcWW^>K|=na?+pXS)PMeT5rmpOwP zoIv`x%Q|+P?H!ix;@+zD?20sSte096t_p6{y&dFbTdKVV4q z0Nra8#?Nu3ACt@`Dlsc%RR%%d?N@cIuuDa8Xp7^06xk8S`vvu}@%f!cyxCy0=!+dH zhKn<3w88c*D#26jWXEQBBxsZxG23h_4%uPIH!`5Ek2Z5{VTZAEw3+n1Hl$^lGdomq z1`;o@!Gk>Zt_L4czbbuIa6|!pjkdAx3*=bGk>JCkkG6yho@yfZZ}!X+G~RE>GtyO5 zA8wZ9NsV%Ia2w5UH%=X+d9X(up77}yhUS6uCi!y+c7OsI^<}JMB{l_JEy;S;F^TY{ zm`vLj)S`Opc6xuUYjFtggAS=Yy1eSBpZOxKLgQm+)HEk4^;LX3-5LJQ?Yp$UbTP^O zy$bj{Qo|RPcO8>N;yrC+>w?+L8G#9;n@eUA4{CqHYz|`=7#NQF#vhM8GlIU<%Vd(5 zZ4D{%SrdLL2y;C>!U9%Y97wRYci}aRDM;U}zGJT!zB=d8BSa-_^xPTP#5OB;D%-}^ z`NWC4WpU$9qD8viJRe|>i<8(A;siD>&bQ0c&P0sg1-gnHzk5EbY@QF8#a(|o&m<|E zpx5D@vXex_)%omF$1UwzQ@0qW#n;8_C>3WTy>(gI!nQKl0~g%x5zlsW=wmXjiaaF&6Ff1H zi<-%fv4`vn-S20AFz2B>r6ROd30re08?tYLPHexwkW7T15!Lp>ZY-+jqAN_mOqjK{xHpQCaMm zZds>ixHLg@&bM>5u3h2VEVO&^cV5l1P9}v(Mf_dg^h#S8x-Zl$X{2}6xEsP*pAwv3 zPS@+da~Ym&ZL$u+#j%oITlLUT%D{lIwYq{4eTo08MOn_ z{@x%qF+&=g-L34vo)1pGOVX&GriIK&ut{2XWl1`j#M!Xx`JR~_B8{hTdPbOZzPo?w zmB;j*^WvYpc7NCVmhR*Pxh7hX1qh_k9yDI~YTZeNZxewha0$*1mLoOdhgozd6ka=( z?Q(VrtK3;sC$!5taaQ#1$1pFX&XC2vaav%97vo*nWgOt3)1h++@$4kw%H6<1d`_27 zXS5FI9^fog?-rbe+BF9!bO_GnVqHdx-2$Gdhzqbywkr=Ef|u0<>>-Y^DchBYm}!sa zDw~J;BM>5>?T4BjC{!Tcqlg!X&~Y|pt5;ogoKKhXP-kw)(+oUo_N1gkwoB3>k0(9y2w$vK*@c~|eyl8h zT#t&qKTkI8EP>Y@oOpE|XLn;4YKtFM$ZX-yu%mlI2m3!ns2|Su^GnD$hg#FqEc^a> zZDP;(1j)HO^Z!ZO6ms*e=4n_LHNh_Fj8qjVJv%$K5$7Zwe&OSkcg+3{=PA+iyy+Q2 z*ZX6xc(yH44w0_|!_CDgGmOvu&5NF$<5NA)dUlxdFOW9$3sc$o@WMTav&jFeSJD}e zJmL92{v|H~7r%qY|&xn93aVe~_9L%RNAZ&MYK4y|twr8(Iy`7YmG(oT6tIDE>) z8FCA;GRIbXaofcRe_9GwMa6sdT)>GQIjD;Z6JK6tQcL7N;xx7I$!Chpd=GY6Acdcv z(R984{mbd_3E`!gk?Xg~p3}NTdXkL=JfpcK)Kr>d3Pbf;C>dqYHQ#!0KP2!DTh$k5A>X!yJ*sDB1mc?-s++Lxz~cx8-yH&Kgt%0`!RdQ?q&K4 z2U$MNI4VKIn7(m1eTtUk!lvIS=(9VRp6Yz&Ui*YjpVogVygEZ#ij--QLGXU` zeh#DBf|LBV*c*ZpV4bWxcQ@vr6wUsPUM_AJCo+ij>w$-SDsYI&-zy zUye08p0-7^KaZTQ`CbH_zB>Zi%NXTO>=S9!26fHH>@u_jHR%#vD#&Z##%eUePz9N| z3OgOVuoGF$jzIkDGH=Alu<3$E;&ynztA=vz0mygLc5|f6?b#a`*l!G@oJ;` z6nscsqkaMCiHHL@|A_M5jPpbNONK+Q_vc@U%8$&WZ?5&f4f#!M(|Y61OL)w}d4FD5 zKHd9#t^ZxTTWa$I6?xcV;Ej}>9bDkO)2GRZeY}FMX+m+A7d%J_uokF``$G8ITT|T>gTBt_|?~ZIm z>L~tp_G=o)Z{IBE?;DO^`z#@Bnw0l1!uAgPFYWj0@l3;J5n`Xku?_i~@?y|0WL@{` zpe4dT1N1Viq=(~r?~Y)0bI#`cbkJ6dHm++->)5t{o#UD|<*C^>6jRaW*RHy}D-8Cl zcrOVQ#{>O)uUqqKA!j``ZCbC>HTmN@I_L?PL5cloq>qeoqT?Rx)Vo(^ca*ZXh5iLibx z@J9m+CT-C%tzJT3SmtBcl)Mzc_*YmUDbJsczOnJBfBVnk-qna zC{NLI;wV4TbK;~pXO{H6GPLv?FVL*NEw+Gg0gdB!Q!ECwjcXt5uN$PWqGV_lQuKN% zgCnm;oOyLP^J>8_q;B6XXP%8ifwXtGDO;iq<2$ItrK2L+u6G4eTXY!j_tr%xgd7Kb ze3iL7^^slpot65{pHnG)IG#TPt@MFz?6{7AqW1HB1tD{%N{_+MP_B@b!dvf9zl}fN zkB*W0;DbqO1_Bygx zWG78=@o-dGw~v*pV%av#8K~o>T}gEu{0=UTm2}l$6eLLVfQ%M(c}7AD#r%^rlI)LR z@6z6t*$_3$V<;#c99cDx&Wd)%;4W$aqed3~{P#}{%&jYwFkh&rOYFiZKg|T&qA&&= zIVG$l=ozj2%o5hi)~Jui}(bGh_*;fToI3W=b8C1|J6d5vQwxqh%2f@&4mM z;i_o{WSg-QXAAp zYE=-ndaJw)C+r%P)#&joQLQm@sx@oXs>5rivno2K?z*59H2K4$cqGPW^t>`*OCtRH z3EGGHD~4z<@PyrB5wz`4tTEE~bd*80pw))eSXEP$#H7R-zB3#)jIBCsno}57m(Gge z#rV(QK#A>rWt^GeUeaKfwt-3cp*PNa+C%uoYCRWLl;mF(1bu9^K90W+uZxX^7p8V! zySU9ic#K)R6DKI2l{Ja%^R)jo&=Z>Ckb}$~UPnhm7>9)A!#i5L;R_7znea1C>>!WokCQ9Oebkp@z4qZ?P5Ud!9%MVhBmB@&G86d#m1~9 zeK~kP#uf+Q(jjjWTy{9L^yp(saRS^eZo<% zf*j5^pfufoY#eMao|YYE*q>O8`_7C7WycwGNn_ya4rk6K#~C_l1J0fi<>kla-@#vYEjUZyoLiBU=S zzjOx)HQr`~BI!VMjQPrAu-8i1R1AubERN>%0tU_FAm`u8T{uJ!T&Zzh{BL+Ejmo(!AduW*%$y1(gN{ z`x`>cVtbCq75<)tEni-ePbN(}BkD{DU#pF+O8Z@0kuz?{Hh;sC{P0b}W@%JqY>3S> ziiL0Ty0Glzg$03C{$`a~8Z6u`H-vaFU-+5@_Qf98zVO|4S|a#@1D&f3@+dM%*cA>) z+jQXu6-&Z($*^$Qh0UH(#pZ(s@a)-0vnYJGF492zMo}k;^R*bRGhI{bHMFeo-R+T-I(kw`j+lfh7)> zFS}XRstfAW{tPOiu_-;`9C5_Qs*BVgdcD9oUw~gO;Znn2XZw+W5D{#VLIdS1*f25w zZ`PBYqMamc%Vx~`*o+}matU^dcUtrxZjOdu(-6Q_G&tIZNm_BDRh1IwUs{g^uwv+< zKIl6zhu2I`6dUUQaA>Ww|4<)mKSFbt=9XjCvv?<+x7-r(kIjz}i~gC-L;aHnNhi(^ z<@2I8k3aTBe;@9P`r&WT!xE4@+dqhXK^t}EMY1pOF%lZi>|q1_VY>^2wU`U%KAwkl zZ=b;O#_Y>LJjuy$b1By4jMH)Nb02@A`MGz7f%>ZzC3)DHPEXkD1t&!xi{8B4dn%}1 zE;N!Zow5Hl0W3;FRu;>2bJM)+0@j!z#{DhR#25)>W)O}(MNR9*i6VW+9zNpHAU8hDbC5DzN-re6z&#lSUW@id_ zGm$e{*>30?k;2`RSn+HtzfzDA|hh zuHh}uHRr{h!q&T#%rprs3ru2>{3=F(q;KX`F&mI7gyjPAl0{A1_G+U}Gqa}E`LuZM zy&L;0xk&+CvKFyHq$ZKF#!0M?-4hrUw?7=jOxdsf;S|LM&e8-X?6z-vJzJ%K(`U#J z9{Z2roKsPn=l;)oW&7Zn^1a`JUX)KXQtxgjuX=Q@WhR@`f?n4~_56l;a8P*P=Yu5j zkamL28Uo6T48r=2M$Hm`0cMuB6WL;at*7mchA2tF1`whkew5->iWzFRd+p9v*VhIxH`5rwu zV;oqVKZx^1?bvnLDs0L34-Ic8{u($13BO-6R?FA~s$iX?u2I)LTHjFSngtUfT|h4+ zVUx|H?G#}30<1oOwWjNkr1}eCtEYLKE?6t+DgzXZYMFA}ZVHvj7HLtjhe$xOxG@m6 z!?~;gYkGnVVX!8M-fq?Y+Wn~cLG75cMl-AziKH*?O1LGA6(k88y%VWz=X(FjtJs?f z+}?IY*rBp4Wkt#DB;0sW!Gte0gtGxjf=Ti&k51@c)AnPORp;M8Lcl%MS*mIasyfz0xX5RNbY>4T%RZw? z(VfzW3_4KqHtjE`s?fuGnYSOIez}(VV_rysx&QF78VPh-0rYuMlCVkAF5HJRs%MhO zRD-B_3Y!9}7uhXpFRH`Ni@2FKK@0p}qqW1k1g%`mgl>;E(%z<>bmmp9$4Loh5IFRS zSeMlQ(h$=sjeI~GcAB(Bg_6h_29KucY!Gzsn7G0&Q9EW0lD!P$acVP@irJqgX#&== zw|8L8fM`1UJ_8dOX7&sBV&u?eIfJN;NfI^vwHJLwjN115vbGE{ZM!f6$H*gD@NrP6 zzu^h(m6Nnx_i3-4^s$R!S@X1s+rW`w+k=>J(KO70X##QnP>>-B^OQ2I7}!TGFqqF1 z+C?*e=@oIrF6LywD#@w3h2!VLwkR4g7bdLRfw@wCMhsqStB!4^tEg1o_6HP?Xs@2U zM=_RVrg@#ZRa>g~?RJae(*^zT?=&*oT7`M6?A6qx3grShM)?U>3@ft@_ZY;6cMYc1 z-(j{;W-DHOl$KX#K>OH)rX5u|pr&f4iZwb?A&^H|2iuF5N zv8tMR^RV{Yvt*LecF^3(^AY@7Bo1LslY@_N0-KYMUcVfMvD{Gq(IKWI4n|LKQ0j6+ zq>*}f??2{&aV&fnt7TzKa{zm_Uoyz3NLY(j&{IU1#H;ZBHiWfR(sqW`VQy4tl*Nzf zna0YJNpmneD=@B3jX5pP@S*;WAAklWRsVH<}62RP+4&iCp>2vg+};ZM#wl;W*KAIab%}fa7M+( z!^dTmWs>E9`LBUSv!I#oRiU^)ab3s?8wD)^$y+evff+1lCzw%v^J;HEYCy^xr>KwRfbjijoU~^R=`wF*-cm5X0?C%fs*gFe{Wl0Up#}98K-e%qLK#%>R#F^d=fs*|m-prmS zwHLd^tvLo!VxJ9@KZ|Ku=0!QD&z{R0z+6^ zMZK&BBoWnNt>{cEA>7=#^yCc32=7^f90Fp_%}!**dGl%)W}+UtZD( zb<%gGA2Ka(Yj$P-+MSQFjKn5r6(kZ^U8NsN-`$mct(&xC1T!t!7zUVo2h~_z)d#=B z0*kjr$jX&tac0vaBp@juajZh75KR+JWzACaR>;Dw+J;QJ3sPWj*8YT@os>2usF@V< z#vk|}!rDuZ5D6?XiMZbaP8J&V#<^I@56{BT{4jGmF_L9jicLn`92=0llPpmP zc7|CZp`~pn76n>h=X-{L6cVQSsNs_r^e-O0L-G32hm=M=vuBpKuXn$a*(XX#45(L3 z4VWb&dzt+cLtoIpew6H=qAS%;F$nj+raga3urHE*Uh8$T;iK1%mMbO&%<}#%FfriS zqiLd49rw-;y`mYD&15pplghZ#D=<CGQgcd5(0@B*a&kFd!nI38O1EnyS zLp?D_S9wh{gywoik3Hvw`^oHAnhw1e{AG}^7qBu0J?K=KxkP_nGfsUE<_cnU;dT#~^8=Yj_#- zq%3wCJ)jBKy{)M>B90y39WNM*wZ)l&h_8cEjNqC>v{ji_CgKibijh;phG_H2lXkqJ zn5Bp^q^e{ciXaZFfMmJSHjP4-D>oD?D4rHuaH7Ou2_tKZ2nv99LwV;D*xx?o?fXN3 z*O#?m%^~L7hUn}BtRhdrOC>-5i}OrcXIV5siI%PU^+CCeF^j|qdSv2)K*lZ;7s0a< zwU~Z6NNdkbmBU(@>p#ZAByNXh*o0$V+vr-Tlk$(`$FIV#Ipn2EiaVT?39tR~V*yF| z{&#DA&iR}PAT8y~a@${p#j zBNbqsD-h)+&3V5{?b`ADV8H~qz5YiWO z8M@<1x>{+lzjja(BC&-**Ba~}2c8YXuWE2Q#s!zLq6?)R+k*2B*g9$5BlJu-DHIkxaL_F`(3L;p zeD83E3&Lup%e}(o315eRZF{>Xy;>i!$fU$(?gc2FFEO zxyY1~3@$TeYHA8sVzC-mmYGTjK9g(8t0o((OKL3@l?m20rkY}NLT1|3DO2@HS&3?0 z`V?Ji;?&giRBcvT+Ei_3N|IimIoT0!GN0R|;;Jf|5g{{+3X5jWTvNDaCOdP(Oja>{ z({u&9XyYQ5U0%POC5q_^GSmyNWJD1`@6PrPsdF+sd?&`NkC~{c7mFqMik!7{dhhh5 z^)ul|OvjT2;!vj{VAS+gQ$m*GTQo4QjY6Jc3Ixuu#msGS#B$acUIJs0BOH;&3 zr6F>ByhHG(PM?{s_VAtQ>)`;9tiZ1Xe*yLQi-@g{9itj6Em@hCdmA^GNF_poLlQFy z$%LEiShk*KHd87k4OMC)r5{2J2DGkJB$#2%G?}xQdYVo7$be1MvGpjg28c;06Ny$RvlH39vp=Amv zMhR}}MFK`3qPc5`P$DJVf(3P&`sl2z^z^K(tY~~i*QYO7us}hin`8pTV~=&z)k{U9 zI+C?f1NbyENWDBd3+M!zHlU2U4fHKdn?9h3h)~dLfQCtPkV}L}G%G7&x<IOd`nMs3lDH2F*q^ zz{bAl$mqTe3l?V6`fgaT!BbYBn?&)K0l+ho@^W(28JU@3cV=icTpj6rFHU$ z(I+r*v$fan*R%LJO=FZ4w}vZ9}U{%%5mEBjw?2QX-|P+A7% zfdPCW3_!{OP{0tP@GlVv!y#sR=m)=uimZqH=m$iTo;8q{mzT0hAn@=IY{Fmh!raVa zyqGT1Y~n&V8YpOey!Y`|Ha0hwon6gT&sOIZ6sXlXbvf!+S1#4hn2Ba2o3No~Q!M>t zWv$4{(%hPtrO{;N-Ks%hjL_bIa;4HWYouvo(jwA4{A7L*9ts6Ok;{o%GsG|?lwm?h zVDN-7WI8?+%2A&;;|O{5Swd3ZA*4JC$Ja*_atc=_uJ3Rq#1L`|E|)}}Z>lJ$0d^t|~LG=PFA}|1-H zw{m@r$@(AFOkZZSn)&M7q+I%rt1_-KaqFrrH72gS)>^}@G;x&`+{((@ijwN}>$^oM**zzB43k#+b7LjIVd+GH%@iYv>@jTI&E7Z9mVSPmF@<$%vc2F2F7mI~T7XnI$e*0c&? z&NP!Ip~Y`j|JizOrKN^%Q>&?l#&M;0l~!UguHs6JHJB)|I)VFlu%%~mg}UEoctd`O zakKnfak6qVGjGvlxQZEur6BW`*%?l{cEv?l&hNu?aJexW2eb8mOve{63Qsy@b zvIN{bf&*RQysTVZCe^wev_T`FfJu?+q!O;gv?|(Utr^AtS((}Yi`X=OSB*S<9Ob!c z<9c@11dowcS1nxcoHgLz{T_N(oc|rNRC2sr8m7Hbxp6gA)8?!-#+q6y*x?3R1N+p_%u0JQ_S*0ZFJH*qSNZTpjv0CF{3x&jMb}Z z%Yim4dK(Mk^s$s=s;eSm44?}arqV;$Qs2h zGMlPRc#hAv#OIfw2ondA1D}FxswzLT-eO{{0;lqA zQ$^brQUruHLI)$H3(BTAp(@GmsF*e&2y7h)nJPm(0k1QgDrhZGG8G75;$f0NyYq#N z@D1fI2c1HZa?vR%H5P+q)>oT=c<>m8X1or>VM< zxESo;SL?Ry*@e2?1xx;4s2C4pnWY@4zCrA}fOIuBWCJh1X}v1JaW}G?qxz+_6+Atm z6NLaCmW907p;#z4*15ziNDEZs9E~96FmFM&J6MXM%aN^1*8jfKa*AVqm_pW4abSkx z!xv;Jt_D3(E-0?4F5~;1;p|FGYc0jDE^wuh_F7_==6eZeCt)dd>KQZ@mCO`u z7h;^O!Dlt1c{y|?KH`ndBa%a#b1pGEEVB5H-z7R%V$fBGXf=)+@favEVbo5lXyZ6X*R)MhdO2hU z#-k&x>}Xv+J}+RaE0Kx{l}d>1a(d@N(Qr%Ry+ddtP6^`QB<>9~4f?Z`*OohF>o8fB zLC8B)mtmC#oh7d{QOU%MAO|G^A5>hz5&@Z9?d(ylP@*7XZW4sL4#4T;U0pGc6VRiPAfVb3GTLy}8q@(2L z;4!D7i zS92pNv8-}FP@Fm$)zM`DUVf-IqK~vEC^xt)1qn_pIVEjmZFy!q zN52uDhmGdq;_gJXTFs@Zq02hKa|r>yC|4}JOPr+6999x(WF#s#5-8k!xyf`44%K_q z1GNppcEP`a!tQLm0%M(1?z%uu=8YS4n1w8$1G@bA!pipYyTc5825J^L6 zVB(aU!%p7;%*+4|f$*;yPn7XTDcKIduM`JRW~!6yKa7X!dO-*-BobQWj^To_Z_7}Ke9Is&;7 z&^Y20R=P#bVqDL|0VubGi*g1#OVlkImRWqux?Ver(dibE@?lNEf&7tS->5e(YpKzx z<3nFb8WtyseAY>+X%4QQO;xE8`gNd#^1h>wPMnlJ+?o!N;0WglFx@4-hpimWu?ws$ z|B3O`)id$tfl~A-{8#|p%cw3L30i!p}hMK)g5((c+ZHh{bw9&vF= zl(*2E@uP+t-oTm=g@g_z!Z8GLl;X^af8h*w<}o@bktU`iHdn`w#N22mA0D)Gl*xzD z>SFNU@ix^yZ=MrgxZAn4 zt&?hSPUFoeJDUsEQLp&8Py!r`7&kcqW>uF29ga?kF#5)K&VG^?JK1~(1-Zjp5Qg7m z@YZZ_I&T`|s?qVAxFXtz#&hUEmrWwhs8sZWiUFvn&s^SQv#<&cm@)HaDy6g4hZThX zQK95>M^{~Kf_)7&cj@maksnhz#teM@hs$&7S}qQUQR+@p{D>Ykiop}pqWDhSsnIzF z7qun-UwjdN1&kXJ3a(tt< zYu{ftZvCn|kKA>2L-wY&`fnQIw`{!oldVDb8t;30+rakh9S=V6*@M9kuWUT9^P8rm zT{XLp?fG@Drgcl(yX_vGbNB7sf94VPz?y^4Klbb6vz~nL(5a``!)u;-^;zc6bC2wL z?q5ffUf6K#y%+snTJrLvuk`*k8>+zSC^gi20!S zJb&@h`fT&<_6zqf9rMiC-vVZgZZHxd@2B{uEuC^G{lBKBOxrU3)QrGcM$MtjeyuiZd-e%^P|k|n zC-eT1pIT5e=UCy7b5rM4&3|fvePP(5+ZNxyNVn2HY5MW5A68HwN4oaAUxY0XGKR7;t02jR7|X+!%0Uz>NVn2HY5MW5A68 zHwN4oaAUxY0XGKR7;t02jR7|X+!%0Uz>NVn2HY5MW5A68HwN4oaAUxY0XGKR7;t02 zjR7|X+!%0Uz>NVn2HY5MW5A68HwN4oaAUxY0XGKR7;t02jR7|X+!%0Uz>NVn2HY5M zW5A68HwN4oaAUxY0XGKR7;t02jR7|X+!%0Uz>NVn2HY5MW5A68HwN4oaAUxY0XGKR z7;t02jR7|X+!%0Uz>NVn2HY5MW5A68HwN4oaAUxY0XGKR7;t02jR7|X+!%0Uz>NVn z2HY5MW5A68HwN4oaAUxY0XGKR7;t02jR7|XZi<0OD;JqklED=l%gRh8TzO?pWwoxh zy4qAx!$p=5GP$O_YO=Aqq}EbVnP6RGswp-nWTs7>GF6|Hm8jOGPtm0&PEAcu)n=uo zP1Repg1M6_B{XZY;6dR8w1BK?`=h&#tbntVRGIRx&A4 zom9e=m{t*;v5e#2jmisQmX+1U8cSsbXL6*YMGfaQw{o4Snyak}L)fCsd2@2-+>*g@ zu96nc*K%_zYq;XdiV9P4jcF7N*>mR=7I3+9au*Eer7g@#PUZm4;*tCpn5;FHidEcf zT^1>@SW7K63rxjkLgr)_WO9j9h<;H9r=FCe9t~4*WqG-=qJ*((=8m_Xo#+kAT@o4y}>dM**6iu=#iYrTi2L}O!5pG_#wywy?lFrLy6x6V>l#)GiZ#MN4X@lgcz2YQMHOM#9_WXZg_1)SAV4xZz0 zK@NA+nw$?+b91wtw`)gkE2~Tu&d|!zQsU&BS`w*Fbg~nt_+<($7R8V0?TQ35EfttjT1k~TaA(`dtUQ=+v@@E1wKmOi@t~bs^uB}%$N_xJUn(`06Xr&xI^PBCL}8^D_#rS z5_F5wi~Wpk4!$iUDD+(De$E)C3jZej3Dv5I=*Vv)4^3PZH8J{|=z}rF*wDChajo$S z6Z|KAJn6p4nd)omV~G_>6O;d*yeFj~Rh0HhTIH08^wa4NOx0xkl=1kq+onrqyfni+ zbHc25XIV92nV)9fsg2axba!S&WPg%ft7mU{`xZ-%U+xRJi}SAKb>`2SZJ)ilfSdEi zoMnaA3ir-UzV*{vE%OBP+vg`OII+O6@YjX+-xj>+$Rh3HQ;SQM{Jdn#Qh8BFQS|LE z+&**J`^yTK|84oQ6&F{S4gWG!82gNOto(6hRq+qSWhLL16q|ZXi%LH$)vtPWRg(D$ zbD(91WzbT-`rPWgHGf&7Dtox>N|~|zM7g?RPsO#0<&|$%hF9HPb)iagN9P?^?^sa% zr)r6Hh4q-#t7b*b(Hc?h!rI4cf3D43`{3HsYgOyY);+)O>bhBVTkGDhldaENzkU4& z>&16w-nrq<7w`Px&WU&3e%H>s-o5McT`?P$ZrHxz#SIrX_-&lJaplJQHy+ve<;JTU zgE!6Ev|`hyO`V%w-t@($zD=_Fu=@1+f_h_pZT-FVd+VR5KUV)%{U`O^_2=vVQQuep zYyH*w!TKToZxHvtBJ3Y{*Nr%DA?_1Mb1%{wkw-f6lGXPi-5Znx~r&b**ev_)2Msq z+Mj`kg|(vEqri(-%`xCeV*OL~g6gZlo92!Sz+rgRo0ZEeuK};>iWB9=@+-i#s_ZXo z^46SNUA}q{?GR{r!klD&b(MbAXQhiudrZZqZ%fKbekiUg{&D3UEBlNU#(x>ihKnnf zt@zvW!sYKTo4M?T+oNyqD3TX#S^D#mk|n1WYZo6`6ujvE+kRbWSa@PV(t`H+g87zt zpWd2$>)yH73YQhWF^8M8xxhYq*6hywYk7^rk;x=7uf z+D|jXGOe0-XHA%8p83)Y$&A~kKR)fJ3{A!ZQ%|Qyq*qRPB~6r8kh&-3@5vLBE0T^S zUQ=hP@0zbZ6I$cX#f8QhV-LoB6Fo6{Rn(!0-$q79u8Md<^-Z`c+!(f>I~N)h zdRs_y@Mo+Sdy8^Q&})I070HT<35UjC7{`uV81V4e55_QKGW@IMhy5=4Dt#CDJmCGd z*EP>%&(*R6($f;TB*&v({G#Z4VT7Oyxq-0*dDk{yed)>%mnU9c z-oN{|Pkt5sI{lZLpP%{Z>mS)47xq2)!+ZZV^nLpGcl_(=@4o(L$UhhVqv_j^dnLWv zOB=s=`RiXUsxOvbc1Ejz93mSFb0%e(!5%UY-2vJ%2s-O7bf^UcUI!^q2Ph<;NFizj)}F z_}I!9jz1szeErd{p3^*c;E4E$`OhE!De+HxpS}K!>6uRsryYLeY0szEK6T+x;i1=_ zjDND@3GXL1J>K_N@ne5GIQ!sR2c{l4@@UMX2OeP`Y1tpJf9F2GeGhf|c0SzU-?6J* z(caM(-u6^$V(ZH-x|UD(F5P=+Pt6|Tp61=E-N$z2>^j$cN3*1PUsGDsXFFH#6z_br zaaLo`!y6wCe)x@tRzBqM(BTJfeem)Fk3Nw1z^^+V-BGaP+Wk-8Uv$6s{cmiq-X68R zXWOoAv$u)29lvkGeN*r2zxTy^*WR0c@6~%=zvu3Ia_{lK=k(TtTPwC^Y?W^P^6n?@ zUUzry-R#{zZh3#pzAbCF6mE&#;<4r8<~KJ#vU&67;?4Tav76mVMH+VL9Gzc4*27*h7dryRo$Gd36nTfbdkY+v7?n53Q zAg}%gIr7yb|IH}p&CM4#d!XDxl)n#f{J4b$OzQyKmv>76X9eIrz11JE-;Fw4y(b;@ zdGX%PtO-`MUAJUo5>wfhTzmtS|}0Y{e~xb?xq4|)J^Z#)zX z9QHgstMSoBG4T4?&a|d|O%mYxTyxH@W4lzln|BM*4wv>U-TUcYUCYZYiLFnyhPQRJ zDcX0n`*%Ft;oJF8r{BJv`vUg2>}MZ2@JP&~M;@Je;H?9*5B}|7@ne0DZF=1MiH;}Y zpM34f!b2Aht$oV#=|`SUJN(IE(=*qf+52qbpFaMR`Oo4b2aaf-`|7#+qoL0qe}3f) z;$w%7&3^I67x(;S`b!sI+VOJoE9YLh=dY7rJ@e|luO+?y)$0$uk#YPV$6MaadF%39 zPrY6Aj?cTt-?hFM_5RuS8$ZyW7&vkCL(4~DAD{lX>683VMW4O?*?L<_*AHEXPp&!@ z@%j1B_kD5umqC9!{kN9x#itc#y3e$nU2;y@bFOFK-wj`>?3e6MoiD$jzWB?mQ%_spjYDzleVQ9!8=gW6=d>4CpWpsx2$QhzwdP21gk5Rd6dY zDq3A@t-*K^Lw4w{jxpHqPCsD94phCxCyRm@$ugGz3yag0ER!>q>gDiq<&ek5*r zJVqviOP|6QpgxN)>$ZPiE% zjJ%`uso@96)B1w*M|} zIfls8*1#JIc&ow)+`zH5wwfY~Zv(64P7Hg|Qq;DkGnk~4O9=BqdX1^4PLnNDKl21RkNuTE|E`4li&P( z(&+F77RXwjnMca!d8EKnF=JGEN0_mWhW)Yqs3prOK6yjh{Pot^m8kcJQvfJ=-k9@h{c5b&`G8HeW^ z%cZdh@xVp%331$`U>ZV*1eYsZLKu8#2q9yf;ZAsjL`ZAtfNBIDzF2I5d^pXG-Z^rm_!RKZ6m}Y}aJ&-{k(7U?SaO962_s@e4!qI49XZl+Xg)N= z0gEeK%!iBlc&>7398W&n0l|1Y(>t2l(Y_A+O!z~%13%sfr!^dj@6G2=TmQyzPd=Pd z%Z=e)d^ioG??&>0YK)H(*UiFddpIC-!Rd%k@pZHCz?+0qywLj6vgyZBUrLRH(E9#9 zoW^nChu*v5(|Z?wejiTh!GYNu<5Q}>SvaM)n}t*Qxmmam!YR&ZJ5b1nhG>X`{wW9Z?5z)3$oo}|K9K`a%eq;hR3A~-*- zFA(zXF+#TE8i%VK&l~Y;!SA!UL_(Qp#Kb(Q!c;@XFhuZ!fYHdt+}8kZ6bP9)Mocm+ zHC0!-awVkeEkYiBmXPQ1`#!GMa6R?^u=gHNQWag>Xr0vEGt-k8CeTbn&oD$uGvpkG zC^;#L3X%~J1WAg{D1tc*prQ_niW$r(W)KxYk)UGE2?L55UlIQ2*;S_}fZzLn>#lY0 zT6fWFopb7`y=&LryLN>>=TtY2%Wt{IQfGgsk8wz!_>De>Bkg0RnNQpgSO1uga>a028ys)^edNe%Xi&BrKb)Qx z;ri_5@80<6p7PGE?z#8vdVloq(B+=rdi|4nSJCPlui6=UdQAP|S?eY?3QSFJ4c_W9 z>NRV5LQGAaF;GpKJf(M^zN%$mQLEN%+O})op-0c+UcLKN$~bfUgo%?77yPy%pGN%n zpyGO2TGfvm|Csz9^5Gy|{i7Lr%Evy&hx8cC`2Y21=#UZp@o3O|4s_Frg6{fyioSNg zR$njMqOWHilxyiF&3h<(cGZ|5*Gt~HQLdAA?BF#vc8%Q=*M0N*wd3`Um64gacK@op zwet&eOFkNsIgjHV$N39z@bg>vNQtGB$Ir(-aNGmO zJ#gFu$31Y|1IImZ+ylowaNGmOJ#gFu$31Y|1IImZ+ylowaNGmOJ#gFu$31Y|1OIP% zz;c4Ab-R_Q(oLTpIC$vr|HEoaOG~RsC@tNzsan?m7HZWFetJ|n)Q0+Wl{#%6rAodK zN{<}TERtok&T;s!x)Qa4ENNkefsnnym(>voX+#Ve&h907OMWS&_n8W!>4YlxZ0d*F;8r#xR z?~PFEuU3|Nyp5%{Ast2j8%36yhxAL}9pBDU$#`pTT(PBYz>z#gsVS||L~Skg(Wy!; z0B-`y6rQNmo8VpB!BT@z)`q-3kh^)9QbkCQ0|CZp~2Uk%4&60K5m0zI*_lz(U_&k^T$zehi;nhVqU3DYXIVk)Tb3uL8(>8pk8> z`NNRcANBqYIWDfV;k(TzE7cI`pXoR7=R)2qz?;D{AJ3<*bF}>Bi#|{ zo1nu%qz}V}r{JHxY&X<(A9UCaIk~W*KhguB&lxy|L5J0#_eMGsGPj}Zo-cHFq}6;;)$sH#>)RkcDrm9=VB zRjXE2wQ5yWtE#b}EWI5#o|{(<#|b7;?C*g#xXUD+;NEX;n)dm7Ptz&=KJd&Qe!ewD zsb2#s#`kbz71?UF$saUr!kk%rh1nGN8Tl>2uhkkl?QD~O^;ArR2`biW8a8~#bJ4Gn z{|fm1`l?^qoBz#*>byQ~garFO%XaUXD({&lnmp!*k`!L^!PxCWCnmfCm1emGcEBqL zD9bCr+9&8;(S^pALR)shn>t)gDLn z&(yDu&a2MzKjDpuD)uL2?7$qsvG2bf^h3o5@9xI%zG)ubxtp$3hx0H8-LBN4wMspL zW7`urHX#ijetI;->C8!Ij-RHiD3V^=5zPjvKsY!k!K&fbv@)%1C&!9deT$1b#v1h< zJSsMF)~p$NBXp19gJQjBj-NDfA~q`woil3!-Z`E%XKv$I>*np7w~7_D#Mn?&)IQc| z&ZHT5MSfD_*ccRPG07BZ)_QFFX86s7vnNcAaW}zS{&qr9%l55`icVL(G3262@o}wL z$vD?b!%N6m0u7Z+eX^}U8Jf-c4V-RnJ7n5c=vwBqiXf*x<{dw449K9{uKK+Yei%4^aT+)f+R z;kD_?WRD*79946QdL!ABJzx7W`5lfRPYxwtmV)qe6WqVZ zYK2z8f&@2!AWCG86sQd(1w_~&2(w-HWQcR#4}ucKw27j27=wV*1oj5&+~^lQ$uAnz zq9*$|N#prG_B3ARV^<})p^neO?8)d7VK>xi2(HO}V$inpMu>NZxI>N+jb4JRq}6nfUgU*Q&jRQHu4)9!nUT+Ahb)M3+ z+)&7}kVu!POt7?|x+-15GST2VDqZ3-Nn;q8E`gbB=s7A~EKD&tTct0mg$mOQf0{}! zuLGQ}F>Fr1j5x#KM3r7h{+b4dRJu4JQ)74`JrCngC`)6@QR(7_Y=do;E`G={7>=kR z5gV}@q6uqA$krC3%6N)xk!wXjfG>tyWi^$$LHlBabpd@*9|J&Wl#vBnR0R@XhoY6W4s?$d;*GFG6j(CJnK5K#AQt3GfMdM(=F9IF-* zy6(9~7V18mp>nRlSt|W^_TqU4XR7o+IbJN#*iJLLEi~BIZIR)R>vq2NP+YggLR1+I zsoMqC9a^{Rt+(LCH?(dySR1I@2RMap)UuqYN>9f48M?{HuBFm{jRD_cFmxSCiK`8+ zVRXG!W9XW`gfXzj&@qN|rhqAxZvO?%fs~Dl* z8w@|)Mfwj0qi@_m`hJ5Ed)jY5T6aR2_S;WFR2j1v$p@?(KuEPh0sB#K4`-H8Rh^k|WeWYSOkf6agyZX4n#HWS@b;@Y5js*=%ejplw!Yuze;H>5UmL zL#q2}sNEMtEo+$Z)AJ}B8g6$40kX#0=RtulwXAXWYe>`_)Ki7d)S|FWs^$p5@dgG| z`q!>?&bFNNc^DdUSYq9M9p5qd#lh& zBMWAZ9E~1!y}(6jbIt?OI%-55h{#1?dY+y0iiGCKAeQ6@Ux zG0=~W_o~Ija&?O&I5$EJ_X_Ih zNHo}QktBot=m;C^M@Ndmaa~fK8{@j92~lNSh`K}R&J|jh`p!~}iBD)<8aS(w(7H4< zvV2_{8SLxQ*kC_8ni%Xy#|Z}e(b3dkKRTKl9M`plQxBDEzqJ&i%D9x{b)l050{qtB zNd%5zc7fkc#4TzQ9RrLg6CDE$^rK^N^_qq_JL5GCH8q7<(=g{nUDKJ)0L;bZx~B2Y z5+rnVOo&&dqhn%4T@oFW4ECdAiotO!r#c-VOj|ikh$>?c=l!#srXaw|#ZG^WV~w!N zg_RdLytl4fesruc*pH6e4fdnsPJ`pRu625#a_zUf zgs3u(K)2A{PHPY_13&Nl3Z>Uz^27A`f^#Vn=|A8U+T^T<7~8@sg?DB`n+?WlurvGR ziv}mF^obnTUeXv}tJ0TYSPH#t=m{$QODqOMuNaJ#hs#y^R)d2o{TEpk8I1UQl&jHg z26KfetMJ#H{c&4f7oy7e9lD2hIG<`;zH=@`$+I90wtVjlLqgl~gOLSW>Y@XO_8aWm z@}t4Yh?)MwRp=*!!pmX#|+l`)bn9Chb| z09lRQ`lxw0#&LM1iQ55*^nIK^PB60Im7Q$irUt_+QdhHhT{VkG!j9$!!z=wq^iiP} z2E#4l)s_ZxW)X2z3O@D=7t8icTu-KF>nlYtA2+Z zWH7!%ZbOOCV1v=`bX`N;=_suIFieOl0~uIDxo6;ty2iU#;>%hDenwprTnhbv0(+ zz0qB+>$=CSpNFk{_yz`_-Rn+7BE1c@xlhYV!gri891R{YvTNv&UuR&tO5ejNV!grm zYB{j?U=?~$;}8~-y7?Yr@rmY3T9pxZAxUUiTg$stk6j(3|e%Ai(9{xa0BVeH0d} zaKk>gGZMP4Z?!Cb-4fZ~8yvT5zgq*$+O8js?1{V)@RRF-fQjpfdjO-??UaqLPTpmd z{Usa0@?=>9QN~BMcXnKsBSe+)3(AIE?@TQ#-P;vYYQL6M!+R?(E2Fxsn%>iKS(!%G z9+VAbdFv_54b}6;U_smg_laP0ffqwU>s8;Au9<*l*KOC(3xKF?Y$QaLaXJ^%jlI7p z%MP{m`a;j8lx2t7c{Ad&+IupbCBS)FR!47mTvjI`s*L`$v9s431TJU1orsIwl!fJt zw~?}@a8MthZRAfzXjy~2TjR0@8yj~sriOTBTGkjZ2v0|031pq-xkzYPr&pIX*846l zYn+jlz*aib`$)^0={1J2)3mI!y`gbgv#QHF$7>6s_SYOE>jaby&Gj0CkkvX=;yn+W zXXfA+4T?ERlzL37Y#A~x^5y`z*|`j(i@gN^p=|l`zrLh z>ybP50hRL{(m4#Aj7^NF<=#AcyJ_e~?=|3iuqe^qUga@uynU0m4#0T(X73R$U9?Yc z@ty#vsl8q9Jp*8Ty4u?WkfptStM@X1@#$^ec7Po1?KR#`0OQl!y|)02Pw(*F1IX2` zztj5|!1#2n_XU9Q>0RDFfJQ2Zx65;Q2QY_^8FKjTUHgXL)O3oga-HJ(D2LOa_7_Lg z91a;7JLr|Wy)WP<#NY$oiD-(Saj!#rWu3>g@ydGd4*=tp2fe=mObp_VAX?bO;KQB= zkgWanh?fXpV(?Kf6~OrGF|Q_oiNVLcS^&mh8@xIICI+AI>H!#kJ?S+9F#g);H3Kj) z_>@-!VEpy8*ABq=>lv>zfQi9py&eEfbqqe|^#MQ(@?L!o?^kN)@Gh5*8{U=B{^K`L zo#M9*o#IL@htt0<#+f3AL#KuuU@``9;q$!r7g`M7-QsmZB||VbYVW?}F>Sp2vNsaI zc=r|W6waW!hi~=H00?KxeWX{t2>>ZN0JnKl0aCTAw|l%jXk7i8HwVDD`gLysfN}K> zZ!v&z^&8$r0LIljy=4H#)w{ea0gS76d)EONSMTwz2Z-q&{-$>`fbs5I-faL)w0Gb3 z)&ju0d{~gfJFeOQmGzY7*$TUQTii}01TdLM`7^7`X-^k{Bt+IVtiA&S?>uts|c!T_Z9b zDrQ9HpwHIC<1tj0*nvva`W(Kq6FYNwjkE(#Nu&h2tH@ZH8o8(!=p+mirGdy9xLg#7%t5o1 zh9c+Ta#1L94f;lDV&n!~E=p9+7f>>B%yrba06N-<6ThOqW6@$IktG)Oy%7~!k*kol zBiG~XL~fP*dvLZQ4@>@2l7BmjLf`vwfxeGv^sGjoK|1vP4i{+nt44=3>W_eczPVc8 zHd^1VTHjt;-$6#-`Y4gOq&sBRdI9~|N?e+W+x(HwrBvk6Rz zR~`U=Z7cDbcVXvU5;b)^CgiQ$SJ|IXK0Xk zXAC;jdKWoX;=S21Xz~lxDT(YuQbp1c=2qk!r0vL>JZhDULT+R!3VD$RXqiA{9NZ9$ zv_PweA{U|w6CwxTfyBtONGC-;fYEMb2;*2e@1dH+ryoY)+}$XZleq0#h>mWjV_u{4 zR5TeGiTdGWv<4a>aR-$OMU&}lc}f|M_Ji$-JK2fSqTNv_aTf!nM)Yf@cQeRqM!TR? z;vPCUOVwHeK~_@Z2ay-)inNL>!O4mohO=z6M!5Ei5V@7)t5I4-zGXjE&P&J**I_a6 zG}{V;ekKnWE-Lach*sow_!w=w4YY9K9?jXhBbqA{?uraUEUL&zOtX;I8M)zhhcr*e zi!m;BAkP=DUPbz15ChL8$PIUiAs;n%ABN0XBWU4K_iN74^+DQC&XHiWA|GL#fwYFm4Uc(C^PF)#3P$t6(@^YMCDQK4 z*^UfH4)|{bM|i?P%|AI6onsLB`@(b;S%X%!BDK(Nc4P=*7X0bp2v2VW9{A+!+Yt!o zkiQlDuOi=(UpaRoH+;@$&9itO8t8iR#TzbJjQl$DVu;G{wd)&0SB35z zev3&}m-*r4k0EWn4!(DA#E9~QoIjK;czqkRwe>wns-90~=;YBec^i?f@~=z);|)KO zu_l%zA*$Jx3WxoavYhY>yD^409!k0bZ#IHlf445igqqsrE( z(b@ybyA{+!q~2PFb{FaaQ2wZ(c0^=`Z=2|sO({S}#33G3_5Mcdhu1WO1S#7Tl%fi1 zF@xy#{%C5Uo(Rg&3hFwHF5x>qf&3dG-I@x@*%j0U^!A+x;lImCT?R^-Pt9WiRqqqV z+}h0;+(rC-AV1`@sQd=V58u_C25&*`whBrv{ZZm?Q_-p1!q`5!Yr*X_gE>W|zZ6_mbo-TD-q ztqI7TRzdj>nlSv}WCr*J$i2*`Xoc#{Lq7^X^dXoSbJiM=@Ag?#{sG3v!}n8_r;+=z zPtiWhe+tbUeq<3mXT1l~mvJ(!QTeTK3O{-$XO4p)ISqVcwZ{j>Kz{6HG}(GETD3vW z^I25A(WE}!3C$|)(E*fh71SRX>>JKRNC@?0P)@I)-sXV%!~_hyLY)W7`4!ZEkRN{X zMR-K0D?qs^PR;)u>V}`*VMC+!$ld5ujLC0vEO=%zl(t?6>76)Pck2U;qUTaPkiQ4% zXP>O{w=zJVpW}k!HN?D!Lx+9-ssJc2EMixyi`@DZlyz*?O@r7l9gy3tg0c*jhc`E7 zXCHywQz|Gs>GT(uvdLy5ccD))VeWAx*)kj(yT9UPA2%O7{xtI+oqm7-yl52IY(jD(`fLw}0g~@qADgS5Rv*JYKsHXDPc9l$$H4 zE9jxur~5iT3d+U`>RD{y9iO5bOW9qZ?5&_)%MSX+J!oX1{s_u%71Refrta+HQ^Sq1 zB*9@uzt^eru3GTeMGB{2xDB&RV_F*&ysgppM?GyE& zQt%(@y|)OXCj<3TP;aclq1oy`#VCE}1UT+)pUjsP`GqIJU4zI-WCgXx16#?(Rujyf zyAh-+QVX_OkrK3-9oY{{oX9f>Xg9JIUBQc-4uOG4ccg=ndEg8whu<)h2R)Bk>hKPr zo6_u4NQ-`e?35OlL!_!#7eSs<*ahv;m;-NT(EH+ukuguRgdi-X=-Wj6R2@oKV?mkZ zv#5GELA8`tlhGH1dI2bx`P4iPI;!4e_$;OMC}<`uYe2r+XHoe>u})2Ca~jUp)5v|< zr{w+0!VTU=bEmZZ#Bb2|d@`LC2B@2SFg&V^<+BvOWb7;;tEu2MM@u=v7DD0fafN-Pp;A-c5roHGR zh+$_j(}CzFG>~&4=fYt02SkTc!qrMBx(6P2E@Cf9h|Z=5E+&6s^gkF`oh5%EofN$f zE$>`HkA>?}2j>i`VD)OM)KnZXqC8oAv8;GTpW;)ms+WZs%sEq`9_&cL`UmB%jF)9G zRc|E1&l&$TjFEZhPLLmrvq+TWiP^+Xy9R>JRXWRRB^GpRDrt(>v3HNuYE^Zm$Z;5sIAg z5d3M4M(!CE6!skF>@A2gYYuW3#wm>^;cw2ISx=#dT2~==d7P5J3;oqOCnE;R-N=2! zr%2eT{4uO-&ISxL*2^I6ij&2O`CXueGxs1%e+kl0Rmly*6h40~hA$h97Q!LMtNN?9 zgRtNkglo2+nI|4W@U25&Hf97n?LZrkqsdGRgG`(-jo$9T*f>EtP!D#F6Qp1D5RDSq zIhtl;hP1moSFp%>Fx&F3aWimF9AJa0WfhL0fATE*r%VNZ&mR4qB6SR;_D zCgQNlUjpyvEwJZ^$}quC(V1Pz#X8XNsulBEKm0oKMlo*?jy6+JkRNzKS!420vh7@C zS?&DH_9cMRiK;P=8~iWKCBoc+X9iqHCJwg2qiXPXvW8hLbrwVZLY-yLtHf4j*a|C3 zu06WsbADDQYiO0?yW+(=vtq`yVL?~sDBZGvz7uCW3Mi~lu?-;_lp)3R|J6R*_Q14FGaCi-dc<9OEA*)>{`vPUpH?~qtZDAi~ zRceXmRkNsB56Kz|E@^W1cu|lQ&haZ8c&rLFAH)1=E!Ig?MQp5d@x#Vciy}nd!N)AF zT5{^OW{@=vhgJR>b=x7b`_h zb^axf`}`}9;=lJ8{7b*|`JX+Cf7dbi%W9$lPQ9eKTENq;|DvF(~aJ{WL(`Rd=rAB>AXdYovSg>l-> zK_nF8s5ZbCRt)fk6$5;s4DgM)=y8Uj(Bh*D%7zs^Gjypa*hLEV2xcLM^Kf?&L12}q zVz}(d34&SenYF6zNB%UK(+b`> z3?>u$m)C-vnM_0Q$iXUgF4GPAjToU)uVXT;{})$-rHtw9{)etYdO6cs{YDfIP^l}J z&gqB0GF7R!F^#v8iU+FHHB4uo$R{Aqb)3BiWWm)|At!WCyfZKdPEKpj5l^p3*}!Vx z#B}85bA+p$I|~Di-JS!JqQT-6#&aI=wYC6=1pNOms; zvM{OjtkJ?CPSKdhGe8m98|7qY{X-}Emo^!9+Q|2r{t@fZY=KQzqWlqKR zGN)pDnWMLtdHuMo84o$K)6D64E|ZHO-5In@q*vQ%#)sEIp5i;r%nq}VTNk+rHE@#W z)f`TRkt({Cc9@xMWx{ld&t$1Y%k4O?0FxxLk}S8=1-OR$#Ng-79B}0iG?Mu;mfLj_ zNXgv8;&vlRISWwE?M`8kGO#V0>wPU{&=yMJ(|vb{mI8JyW#|KODZ{js_9*8Lzl~CC z_ly{14z!_*?T&4OYYP5x)*ZJ6c=(_KG?$`M4dth|kT$M6nc(HQd7wBc+HcbQM ze<%=dHbOg4KhiKor3@Kzl5#)RFd4A7azD{1j2&FOE%K>`Nw_1zFV3H7nCQFbiwV#` zJNZkJlw(6Z_p6hUo$9*j7VoZ&aL|ohw}#abiF7(B!xA~rH@#PXsF0~~S_tEWG+wrq z4qka>#LW>R-j1dzwJaBenqjxGbw4`5g8-S+SA)>RVp?VLg$?%v>oEW;^EtLvQ)?rD zow<;jHM5=ra5Mj*u;$i_03nsdXv$(RWU(!?=-w=9o$&zba9dbok(NmO0tpFM>lDN_g>O@OoyE8qw2>I{y8MJv;v}!Dc2WV#dEF=sQU=b%@HA0N88isj z@Bt|24X!3-NE?u}l%ZP6ER^$xHAXh1oUsap?$=VruAr39DP>$WDQBJ^moi>UxtVMe zW@#z23*n>#TFN=^QOaGcWKK0Hb2rDOoU5g@LOE~V1}){{BG}g!UmD?;C3SI488T|5 z@-C?+WoZy3ZP79>EBw)%Bj$7v6gcEBwWKMQy9WdNnzTTRM+E8^lY&5bV<;R{-Y#8o{poxC!h->%} zN;x39q@}6w?0mqV1!CX`|Ada<{i0!t3Oj_qYM89Ty(s#34HHzj8_WJFkfUA~!h@RX zsPHN}_CFe85X@q|e`^@;GKcPuYyS^P%IQT%9=;XXsg{>(9YBripmv(&MJ>KlpM7RM zFx0VR{6?+WQ;6#t3<)x@crj}lm}Ow`@`Q+Y3aNd*bs7keJ={8}AzteUiR=+pDiYb^ zjFDOv-nYvZZ;UcHpt8jsCmHOiZ1KlvgE6e=x=*!Uj@La#h$>?=>hiG95rmqh-q}_L zN2~-aV`L z^PX=F1!$RhGh1`9H3^`5CSSz!F0lBD%Q%(Akui${TNcNqEDkGK92K(Isk7K8v)HAw z*dwwS(OC@0tiRD%0k$nGFoSJYcccSs6jmgebye0VX7W1}EA%tZLOP=+d(4GaYZR!3 zJ6lVv0z|_-pk(Hda*4$>3YXyWBn~NTsf_vznxz&WgC@Fxj(-<`oXAcR=yUt)?609K+77&)+Vab7K+hxS5qdTX4A=?d zlIKsFpaMf_lZ+98VJxkje<*4A7MgDbZg>u;LlOj9fgAI2mFX?8N-vS1Rc&(Lq#?B8 z!=u2>8bT}H?hM=_&~{V`xBmvp1v;oorpCbPH{u%HN|JJ3pv>D|L^d?ox*HySMr-gY zw`6Gzw&^;24Yq6OYw((ez6P%gjBBt%V1)*6424+jgPkNP=S|cZ*wqW!2!VrV!-pf1 z#i@UJxatrv!9;Ftf4Lklo8Cea#gtXX28RmT3dzBB=ZpsBP#na zE5+{Q%o5WN?bgZi3(sBp95mvIjH*PBb{IvWF5U8JwiDM-hh&PE^@7 ziIWXR2&K7!G^;s$22E6;h9U&{zS$D(5 z)OMb3&4}A}h7eUoE^8WVjRgU=J#O8Lnvzn*whh)Vaoe8Ivf{RF)HrV2QwICCJ#F}X z+nzCW-?nEB-M8&IgMHhc*Enw5CXM5^ZPvKLwk=jaD68A;B_XPe`{}iptxh1owus#x zVfc}@t+stD64@WI9dd06eA<@6K&_*(m94TfiR&5+U2}pId43`Xxl#5AxsvgSWob0bYbWSSPLZ}Z(V9f?guMQzau!l*JjQeIO#8%(h1MEicU z`w`wNa03JEHArMf7-<8wTuc<%b%_TV3=0d02OAt!*^P;Z7>r15PCV3LwC0=as>2M% zP|=?B;Rd61yAY2s7_EB^BXgv|@ZbvKQ3k_sho7VZ(+q|srL_DkgF}9VOt$}sN5~9mavdQvg%SI_sn6N=w~P=g@T5H+v)UNk zCQ7pc8||J*WG|!Kr(`2NZ(3yMaxQqrV9&4TIXef;TK4loR2dUFL%v`qfq>}SVLt%h zCnI(deQ(&eWK5Ty1i*IqUBUT5{<9y#^yX>Jqm5%?->lAo<@1^8;s}}PyB(wh>oem9~zA4 z;7bRAj|@h1*tF*pgWW$4B%p?Q_{mGIQ;hCeSVRqcEzB^|a?Fdx~zckVy91=&2tYyG9Q0i~eXZ_5cFFn*^4e=d#wXfW=gjOsH2{m)=b z{k@1!GZ_6jku7w(!Dz8`;xi0}-P@_*ScB1GyNSmcjE!W2xb!&FVCI9)uV9XLZ6RmL_>Av2v? zU_!{>;5>n5x)%3v(U3Pf!;sJpTxBZs9e9($z5{PI*mvM92Kx?NZLsgaTMhOdc$>k# z1J@YrJMeaceFxrQu(1MhSAmXA2_0ZpiI;JwZiI9EGx zy?8`B@Ihfz85_lT2@ZVM>5ul^l`Rf@&smOycHsM_Lf?TO80eq^xk zz)uYJ9r&riz5_oq*mvOP2Kx^D!eHNlUmEN?@GFCT2Yzj^@4#;i_8qv-VC}%~od;+s zBXGYaR57sQEh6AOG)-@PY{#hKPVg_T%AHpds&tMGNJGfNIHyBfX5&7#G zj6pn|O|BCb$24iS#Pkjmv#-LtK`-=?5pnf}XD}ynp-%Z@w zU_Gd}b62w^rgOCDpebnK^x{E7RiKl>@j<(-`z@kDw|Ez6LfztBg;8Z3qJG`n55a^M zFLB!dmqw(;OWogDk9?cESj(-6r2$5xrEV%%H04rF$-QqX} z+nf3AF9(zeUk46c;(matB3Chexl|ij&h#}>k^VxlTtsW_SBL`$bl*VXR6FpP zI~;|6!QGiOJMg%BClcB3)88B1EvSz_dXW7I@e>B4y}l%V(qOdLx5OI_Mtl88{FK31 zqWwzzw82=S9VC9nU@Xxlu>GGk7)!L$M!?S*jP_ni{Jgk4Dlj2l{&ufMf0&5(e9*#&Tn~xt02dGc=oaR( zjPLCQj%aM7huds3%aaJO(4!wAzilvjG#_II9D~uLHxs)CqepKe_6$akK97@p&|tK1 z3313^wD2Xw2?nEuFDFhk7%kkJEfzKyEi`~Q*W58BM`4#mL1ZC3jS&YHWJ!bdSFdsX1q83ifbn&Y2pU9z5IoJI;BI zrUW8}bB@NQN6+&zp@x<*UsEc2^jY2o5TkqaEKyVU=yOF8ZTUi}N?W@~1gMN}Xzh94 zY!rsIcX+QMS~}weHCTJ6w-WVf8`kRj_-KuHUGCD*7<;exT%7SfO`)-5ykA3O>w53& zIOBtwLR-oBkcP(8N4+C7m4wGMp~BL8yy>86OV^2t+R{fv3vKBJsYqM;gb2XCT=s(} zy)#f4W7j9%$*}yv7%a5|pL%1F$eu}#&%7<@oHBOJCH~xCMD`-$FAPRxmk@txFyd_~ z@mB_8?7EWpYlAU%l@WhqFvhMMiT4?dvFjPmJ>MFPp0SzuJA=_Pwi17DFnY!g;vWpg z*mVti+J1vEcD+mbj|OAx`k449gE4k}NqoRy7!6PS;$2Qp{KKC0tETW)$BP{0elr-H z+RHzCqYx>2?D}0?s6GCNFsh7G7+ZgO{lJ9SY8bc)`o$m_vDGNBIS=*pVm*xmGB$DS z`kkZQ2^w?k`i&BrY0R-}H|fm{#@O{faSMYnc6~wI(qN2TKM)rhjIpZ)J>JS-j9s;8 zS8IdO!gYz;7>pLKPu$jEwD7weTiY9q7W#y^gTZJazWWjAXfRr6KXE66U9r4t;BQ(! zo07Y03dXMNm2A772BRi!@CfuW7$vpGy9BnPd9=s-hzqsH`wFAVxP?;s1)c^IJYE)X zFjA$!W_WygfWu{WZ?^dgBNyvKxjVa3W7C~)3|t-OT%{@K&YJTkjZJ?p4?G#?T&*eS z&zkdAjZKHXJ+PacQrjJxQqiMt2y_5Z_vl+hP2Ho{h$7nZwNjO~_AU{CNB10u?+!FY zVOaY{pf#-L`U=+W3=Bg;Tf0lwr^hbbBHpdBvG%RN`Eky-HAN3z;M}XRvG%>dU2)F$ zHARnJ;QT;iW9`R*7r=?(3zSbZrNY`b0}Vmc*1juhYHL3dMYOe_Nmbg~&qaXBXv?LD|4f;oBG2IXjGOaQjkSjU30>I5&!NyJrt^)AnVOtI&Jh5e_tcIh(F92F+%9D*c!F>SjGx<{+fx5x{039>sAxA9u3qa=_ znUC{=e*$#R;T)153`37znfwioK)ql(z{pH_Zcz~AgW`#q{Mn5_{UEnxP0o}j7!86k zfT@`hvJHdv0cJoLTC`EHBfxBx#b)mi*9ki|8%F2S{47MC9Z&dM}H9x6I2>k!P# zdegy)vzX@Q=$ge2A7DSAnm%_Eq-&3yFag7DFoej-ea^_ffs~KC1WLNA=$OsNQ=Y)qC%wdhdO-^4|O4m@U+| z0F7b?C+1+hj>_KqsO-Iu%HI3vRq&i0mA&^-*?S+Az4uYsdmnuYR41zU-beM``>5V~ zAJu#Bqn|-~sT_ffs~KH3YRSDF~Dy!Sr1WG;M~ zD|_#QOZ!n@*?S+Az4uYsdmpW|_da-KJ@C}Ag0lDiUGmG``>5=_k3JKkWwQ4^`X175 zbRW)MRQBFSW$%4d_TEPe61cC$!Hv(vsO-Iu)ujVM`iDQRQBFS zW$%5o(%$>vog<(_uI#-J-g_d}?$KWm7$wnt2yYdYz4y^`khY_;_dY6n@1wH!J}P_f zqvPPXU{vh>y$|kWCrXQTN1@;@21|HPmo9SDpm&>3H|U#3d)Uj zL6r&p$>QacpDPWk5l(!1SdT~*aAQouz&;oWte(i|7pK&}e?BNfPJoOzSo=6o_#9Nq zHDFeQ_i$46r@?@PVcbqiY+VK(J_9oHKY&RI!!y8R-GN-*kJb{XqAKXh!Xpz|{brC} zuS#xMOv^^?h9j&G<0RS-KT$x){Tj4f*?pH-%-Jt0yYHg1`z|WG@1nB%E-Jh4qO$ug zD!cEZ-7%&Fqm_2wB@X%(l{8Ai$(rQwZR*AoJ2HJ6D{REghgN&%9Oj2Huv+bzgbv(> z+sI+5KF+oAQhju(?Z~hmw;pBwEtK#$-PCwZJgJ%t#dK<2(kKt_6@g@xe+GQQ61waX z+8V|v+_VX(D*>8G&6i8fG1asAUMg~xcz$RLsyrNwi4=2v4#c$N<1Gb7CB%t7@uoIM z6KDIx)x(b_awHY8Yi1oyyv!%wdDYRxl|J#F`;I2w;S(Qtr3$f-rabNwAF40|8yd#GRYO zovJPSh4mG`aD*(D9SN2dEwEXF8=IJDhNfsii5tPQnDP&C^HozHwr>uaDo{Pe+n<6- zeD?aC$ksN1rkmmypSWw&(Zs_(@vV=JCbGAP*mwSOG%?2~ewYo#s@2JLij@4cbroWV zO{nh*_;Vn#J7Skqn~vB3)LM0V)#Nj;HS;>aybeQ=yB6H%8Sa*(v{4;KBmZgSFE{yx zCV!mazrQknTh(Ez;eW9*Kl1s`8|A-WnZKRtu+Z@TQkft5rG`HdEksR4pPs72WrjcB zo6M$w$TAoo3s(U zexAt>K~%i$;KgMoKW6f!{d%fS%T0cqw;hz@xNNnv%0bi04MC}1g_V@Mh01Zb1{;Uo zw}HEHwA+X>SdS{Ji?s!Xx^tVM>dtSOI?$g5U4rgOZX>IRNa^CQ`oyOy2&x-<@E%Yw z-(ioZ^%KRi^E#dOB9}eB2cgvpDsVJlE>_6O>Sl4){XFxE1XZNighHPfml@KJ!AR;~zG(mQkN9c}$ z)*Gn$3gF_IJqS4%^Uo@Jl_Jsm4V1D5TU(GWM`oW1v*s#mh?Ggf1k`8lw6lFY5V-HR zm`u=}D6{V?6=`wx;d;i^Ct0nFFj>>p3s9&Zz0HISJ9dHZ@CcbW16&E35{IYw#HWNH z>u2ro98jR3vQD-pupB-749a!N1>tC)GgsJ0Tg%B#C+{RX_a#(uyQsbnxe_H8SwH!z ze*tz;JuP5Ve;8akR^IkiuLqh|{aK%=RUbftR{af7?xyNXt$es!RG$lSr|$Ljh=c~l z)+`Q3Jx$1*2g(&Ja+TGcMX3IzlqdnkFML;#daZSaPrXH`49z=0-A?Ld)*?_PG|@pj zLyK<^Jy#=-UH@F<^+KL%gC8BO$m<$H@mk2klr;)d(UTzcS0{3pQ*bY1YyfsSB~9Y$ zFJ%CBIVDYIGIaoUIVDYDGHpPQRw`*Klj#Gn%PDCZlQjllms8SNOlAzgE~ljFOoj$v zms8RVCKCph*TSn^Gns~9>~cz)%XEVQ*yWUT9g}GTxyvc3jOpxw+~t(Coaw9q+~t(C zg6W(A+~t&X8`CwBKTsvDVLG#U8}^1~>tUDYtV>d{K?jhXlFwxjM{`*&HsJDD4d$k& zaC^=bI+tBW4d$k&a6UU| zKFZO5yk+x`x13zW5OU;?w`~6LmQ#NubMzl?+5F=zr@>^&(SN-471VaxEo6?_FXhS~ zZ#jBrlvCx8w;cV)TlR0L+~vzz%Kihjx=k=l((*+$81pn8_r@ zJLSD~3(iiZ|KNg9{^wS}4Z252(*L;?bh*VeBsqEql%xM+%YHuy=4ca89sM6$3ADKf zaN+?Zf-30tWzm5+B|Ul;noYj5q&1$6jAZ%FlDq_rR z5LOxTZpV>EVtRllX`mXx;za;8Lbc_RFq@YQO0k=e)#Bd=?ZP1iRn5(4KfBWb1c`{{ zj?xN|P}rS~oS=IM=MW<_GnAOvqnT1Cp}n(`(Zq>K5k-O6;z9Y}jwQ?VA&>436(vOuZ@nVI3l^jZ*gKjpVUv?bPHQf2ifOUA=UyII`U zn^==FLs^s2a5|lk#dStvCi4@aGp|9HirNt>mvttR*;|o}B~4$9(8ziTWs}a|5C&t; z*o7)-F$3St8N0|N136@Ntn*=$PN!up zfMa#KM%J6KJE`;;)KfF7E5bABV(zG`ll3=r(doJw)GO)i*T7@Vbd;KlBaKMa3c(9W zvz~`+>r&*t;8W76csfKn0h_mgchL2WyC7^O}93A*LlQR+{{t-&6CXaz@_v>^W= zKvfW@gD^i%{9A}+DETM2EZ)fDwkIi>wh~z?gJP}zBKRJVp7hC;8mvx)8rIx~cCqX< zo563r3BG+t^Ge*PIv25RUz!B_QNWP`F6MDADzw%WaaWO|*HoP-_4$1k+80G#DcTLi zPWiW@y42$cI_vKjdA8F$DK!rz_!DNwtWcNwoBaC^!OJKWkWvqz#P)wHCAvz{x-U{q z%i4hELfN2{<$qcQFoYko#!6*>N61+T)(7lIc3Mcv)?crg#W~~=f9U0V`C4|%&7G;mHq~WlCXj~rnMDH>whv?r@6uR!{f+{whJ!gSEh}zu+hKJ)!x{-u_ft^KJFN4Nk-P3B5Zfq;0 zFX!5KQ^oJV@Ozwz5w2pT93w8af8!-F35ygQT8MPtSUG#w750S`(*(3Oak?)5BMaVc zcP873ppA;tb@|_D;$8MXwB;<&=EdoORMy{xf;ZUj(ugZSdn`_usl6gF)4`rDr>)6I z@nlM;I-S|6Uq#8EQAU7;tDmh@JUd_hI$o zAx5Z^)fV*5otbAs5j6Wp+k;-0f!Rb3r<b&Le7m=lYVWd~AL0H<^uX+-I7;-m^lwElLOQy)hg9GYAaUj_WFBFlFF1V4Xu zbfnLtC-C~5oUKHce;1Bf!rl!XXM<&_&sM34B&h4l^i$y0U|3-KVS(Ghye?iq*c$9@ z2716f6KphOlTYTdm>fZuCGkEf2qGl%1V+z-q@{Gmdsui>amFcewVUbh7uFu1PG7K8L-#9WiGUEJDCj-` zqZ>>7G<5OGrINWG-~X5-E$C`K(waO0zd0u$#pj79@ZL8Q{9j5CIqq5gfG7JzCYmnf z7)KdR7x^jtAs^bM3CBBY5qPeyQeXndJF%w;2Q%vyP#>zof%{~0?e!3;nsI?Qqakkl z16bv+fbFR?EK{f&YkvsqofcU1TQ5S@Q3~s?Azt!(g@CWWUPds?Fnu`#zH`KisX_@kcG%TO-`EaVybG zsu>rO{MFBM0j%;}VBVWv$rGheqXpF6PoaEB+XCte*g>$sfFB8_8jy+!RD0n^dVxEw zJIrW=`%n;!s_g|h^9Q@y<0jgCoOx%fJ$|lB>(pTxSQl4j4V6s{%v1S=x&Kn&W)!$j z7jVlauC)Ir=^Y;ivuFSp{1;x;jLZ7RQ2?((z&ZQ}*pq5ha?V^>M(6xa=d2`va|CQ4 zfIt2qWiNpC#~<{^pMV{AQ4P9a1dWFycpl1M@`5K^_ktX@PBVTt*aOZSsedNwezkJ_ z_0a6B|8Lg9r}L~|z$5}R&LL8k0qFV#Ttg{rhY^_7x%L9p|oi zjxaAnfvy+`K9m}`cpfXPrp8_XFiU;EN>0%myOHU zDBUlHgohEie-wx>mMccyiG4Yh@+beA@%u7A%a~t&HQ2w(F@9k61t=@i*l6l7l!()q zpmT^2D*~6a77`dU; z1Y=|?1dQA^!t~Yw?5an$>CwGpaK>O>)-RCHUd_I(A8e41e+MHy-|&HJo{~{N&NqO3 zD7LaHtIQ+AD0m6kcv4>2~U$_^2Fu% zS`9lUn?D^Y%{E^xJSJOQn$%c+OrE$X;n{Rdp12%*nGv^E@_u#W5N^Ex!p~v}w?h!g z7o_5=rYUH93Agh$f@uX2!%fiRL*o zb3FPkU}^r+zK*^N3GFh8z7nP%1BuaBstNtX^p|RxMjI&6=PgiJOd$9|^Ho`|Kz==| zO1#Wde^%vBDLZYYop|I(#AmMF;02g{#BWCaJhecA_TS{6RFyv&a$|lS(kZI8+>)y7 zA;h@RdKgTZ&#EfL@dCA>D!*<p^AJ|Exwxgdr>{in?XgLN^-&YQ%rj0EYNVm`3+CKx^_| zDnBRUu*&~{HtVC6TJt&hPFnL;I`3N|_IyG3Gf!zv0sOB--Cnn`y#@k`o996qbWEJ5 z=%c~{@pHm_^i<+1Q$WQ6a3Cbe2!xUnjKlRb5T8}R8q%wLtf{fkgGc$=Ml;?)BN((kmFPrHQEn+X_*ezS1IFe`#fmD5@jct4 z>id^st(C+B)jX<5Rfkoot39HDcf|Qwg~KY}gDU@sRf>l7Y*j=+q@$sZL_;~SM8nyr3;G7j#s$hwV+TIQH)AL~Qu|b*S^I}m z?=!lvG0&7tXE3qbU{(p_myND8Dxf!LK`z5Xw^8L@R8>%AM;~3X2(IH35Pl}(u*#G3 z@M;8>?(vTFDP6$ZD2>D;VKhxAjtd$#Bjk;g#zGw|)Hs|a)FPjHi%{e6O+f9=#^TQG zTE?9lp#$8hqu=GUD*XjBUp)R@jujkS=bJJ==rX2v9b*vjOK9)wF;%|1yJaGHxVe>p zj)}V}6&1N;9w23R5DzK@9w_)T;?ATG68t;yaMA}0PQb8RypQxDf}_NZ5LI}o zY9oA92;6lpR2weuuJslO-9`w!9Iy>t>EgJ$9^T-=7tnT6up*yZrfU2M4-WwhoguTNxub;z$NOGt=^p%D*t6yYLYjKiA-} z%K3U%&H9y^e+O*hNK-0m{Y3=tYsCL3@7$(6%3WmfaZ)E>jyx9$FaIrxBacSQ$t#PZ zi=?r)19xG)Q*rP+?Gh=Jf|0K4Sw7k@f)^c~=K6e5GG%qPS7 zeM^RyVTto)qAnY$2OBsI(ar~d{M?GeDn9|HepcDsKOvFkE*EV&#DHL~MyCR4b61GD z=aUL^R|xOjL@-yQJ>(U0SBSZZ=+2$SPa%1Wf*OE@r3`aee!Y}mjx1WP(RLthxyJm- zogQNO4Pv=n)(dUNhmri~wmS$zb~UKfc4JV8#@s0tTuKCEG~#Q$+L*N#Z_I2X6~?R; z-rtB|j7BlUpf+Z$Xg?abO55Enh4@}AEzsyKAZ>xheDhMb-92K#B;fyL+wtisKf3L{ zfvKw-Rx)=fB+}f+M4PQdFju2}K-%2L#oPq=isn8pyse2~u14d4w7HLqx!g4z9CCvUXcniL8dVp zwFT0~Y?VMfnN%3FRd_EZf-xFBNL~rVtzr!StE)=eZIePxP&X~mXgrX%K;yfKCHl6D z1-}CSFWZifpcgjQ?;cv^{IQ6~np84310F6Tw`K_#3R9@FXSK?g@Xr0;CN} zktZuI#7OIC*b=bw-dEANQ{=JAxxj7SN11&nI{{brxQKlR&_<97A4WqKr`h1IE&SZr zT)2y^3vbjBKEBxA?mC<>jGEb7{vZJ&y1a<&KaeQy%}JxB&3E29od7JuVxi5hH5j<- zc-+xzB?`|ZL~FH{`tBh@Yqb&dEYOgJm|xlo?79%8+KCdo$hQcvy}&OC7s6p3gz=zI z;V}(cVn!^!{eEbq@oB(a`NQ7^pF?_Q4%{8Z-+vMJ<2b8v7{+v%51IV$EE!w-adH`+ zieT_%!45?oB9p7{Ds$&t_c*6km+Qpcq48uY}=vpf=s1`$BLp1YfcIhsZBN+yG*i zfgsKRu`6EowtkcRZOGTH^}EH^`W2YX@rO_YxSh)8_)|~>sLOcBIFT~g7=KA`X^#AX z>yXbbTd}m_;tijHv7;&Qi0Z>zzI;RCc^m;`Smh5u>CHI$@>!!bwC^xphV|t=U~9N) z#wY6hXy$jp_%#mk1{3|E2L8z#%+2_4ogdA~7i80L#5vC*XCFSB7mRjnu*=3?7_w!!xg-U5SW{|2ewam0;WN5z|E zCQ+jQc#M(U07oTtILurjy=I3LXk!X!sa?R#2cwk=bVq^P<4TOGB7X*0FR8|k`_p&X z0pp!{hFyl3@>{^l7hfw$?=+WBM>g1hLFXT#5Y^ity>dPnISOi&-V%=%_|4=Ao9}+u zWvV+D+CFl-!&Oh%Ta!r&bw>#MAS}bZi%{>1hImpezZAk`r8=4;9qQ3N;sqJM>SH~u zd(tLh9!)HZ?9GB_0C$~&>RuFBDi9TFcs(J9Fb(em9KxQnMaC@|!gTUEQ1}zOcxWx= zeofr30_P$6ir+`L8v0P;Pb%=`z+I=%BQHyNzK+;+3Vot+D()xb1Jv8kEE5;oUIkD?1M_J43pC3VOs&3m~Ec! ztcPyvfZ}alL}&L#G+MPBj)Et`ue!}6!h8X-w0Uj8Wx&$rxdQJJh&I>oX+pNShHn5$ zn@62HP_eYRPJRxGZu2@~d=gd>y3IB2Lo98s@jPN_bB!Ma)@@!_%6}u6ZLV=^%xSvK zHSQ;vZLaa@z|!U#N}I<-(ri$wxA}?kobM7)ben6ug`8+}zAW{BNc-+MDT*!J>YnbM z>7AL~W%DjOFuUw7K_p8C7nYo10YQ);*@y&DM1mmdRa8I_6&1lODkA2DSwswo3g&dZ zm@!`Us=V(zRo%0!`raRpAJcnIeWy;HI(53bx~KZge#}35-kT4HF2^UBjS4zZh`X-d z4}|y~>aDefI#OuZ*bv6ytdM#L(9`(HS9K&*gnOX+u*y0F9slXpK0(Qs`1EBJeCsxx zThOgVIADc^kF}B8N1w+>?4ho)XsXMM>4>{?L)@}*K6&9DM1}3-FxQ+b&iH^FPVjSO zuz4HF1*PVigX_8q6P2}C+%ubePmHVKcaZ1CY{UOTejo8ApBno|6bPvr zUd;JVE*sZ{E`n4)UboK#I+EA%e!Qk%B(l8l@?QiWYg1?&WqGOH2(%wBy^m0AFh%&# z_jTY{6GimBy#H8?t11!UQ|@nl5&g(4z^;W8LvW3L5}+N+)hv9fS0}^y8i94AcoTyH zZ?=T^akahqGK^tl+$gc|8@MV&hUTy;8P2y1tlLF{bZFxlsC^MWGT$-QtYKBNDPk_% z!}-pEb+^>eSJ^F)zNdDZ^*LO_`Qm}KP2{r0HogLJptf9Bk>e`});%JZA#y)J1~2EP zB4Q@xnsLjU%0zh=eB`X+H~h^J+0RHgG)GixYSd`?X8&0!#wkZ-=c6b5$FZ?Cjz-A~ z`1GT`i=e(=A&BiH%0Rph;y8tw^foYKj>bX8YCFbbEf}*ZmOy`A2Rg z5&qb1GlD0;57uzKutYbwGf%wG5a_DZEan{YM`qx&v#*{gY}a%Fn?^8s<(0`tN^%|1@R% z_q*>uDjP`K@Q>|T8`q;Gg6X;+^>v5(eq%t)AaNpy3qc&$1pfOR%$QSg2>i!4a{j;k z$9N46Nlp?%(7;?Z3GYScZ?xNc7QO zNUO0uTB+DHzK)eK7VkL5rjyJZ+oO$&%^;aI7VkL5W|FKo7VkL5W|7Pui+3DjCy~q< z3qQtACK(xvcN}AaItk9wSk|+&2D?7J$n+<#ST1N21odZ{s&M2V8mpr94LjQRCO4 zPUa+P;z^GOseW-^w6~ny?!8q=$)8^q_Lbp>r6xMpBP~MJo>yM{wt+ylHlGCIl^>(CNv6LmX z-i~xD*GP%H9cf;Pw13Eg3p?IHz<)b3+yxe-QQt0n!aRhC@>Rx&V_stPoDWc*z841( z{m~aiclZuvTGQbuk#{K5noS|ecPP`2nNO1MP^PuNfMlEAAbV~CX6o2fE? z$3-*TOISNyWj=^SQn~w-ONn;Q<=8 zRpuA0J5ZyrG>Z>W!h>%l$)COp4iNP3UA;h~epfHjtl!m(g=JTzZ>u!w_w7=R`hB}xqv)G-W{qZp&RlUB219pd z9U*03#erGB9L4C&(`RBfE5+%9&ODQjzq&KeYAt?ep3|(~ndgNKIum+v5dPd27*D_ynsX0JJ^ZssP^$XD!Cz4C^Qmy6w3}7ur6p6gB1q<)&^%sy(YBpsc;B|OjeKC+Io6YbZHoj{d5vk?xz-MC+d69>y!fHEZN2q8 zZF>iY@ReE@l6B_9v%z0wbQh_dA9w;?V|ds)j2f>se73RmI?cn@9PXzGZ!$QheeJi+ z)(L1w`)!MWD(_9$628$I1^|A0)H)B>lZ|2V+hf*p5ZboKwJzE=g*A2>-LP#fr^=@c z55Jbjz&~wxjA`#7)hhgq;o;ZwJ>bt79=3D8dH4mxXByjg89uOmxAkja`%40^T6LUJ}RLccUT{B#rXuMCfKV?FV&4UgE< ze*4C{56ZOPz7#!$tO$fv#dZ53a}X3Q}V443LCI;z(WCXP62%&@84T zsz}%FG}wN$0MEGDH!D2E=9>jMO&Kpk>-uS!&37ZUuHnW{kE3pQ zggpoVbWOAu!hoN(u1WTLAo2(IRN={56@H>6zXt4yhD}pB6MLinRKo{7n`Yk>v^3qc zw1{1sVQ}IRV0y(Q(M|esp|q_@I|R*hfQ| z?&XgHsyvtHz)yA(0D2h?ElT3v5?3GeG7<`b&?Dl7WZvOPAkmR-cz;BqhWDc*W_Uk3 zG7KNsk{P-!uq8`CmA4pehwFtlYFjEo=VMNMLEBOpx;wC?vC-w*(!}t-ElmyYM@KWm z`_XZf;r-}nZg@XBS{OdCwPlF+=h|mN!7-v(C~_-#O_2!uq( zK%>e;#~{P{(J`cMOG85+1uYFTEydW<@X$Wp(&W%UT#N70Eu9$RyC6C`rUXst=$M*n zOQK_%;r-~CVfdhzGeZNRO!sn@fGTe=ulpy3x&uHj7lry`9^+$0^zz(LDF_`Mi;XUS zM3xxdACaYo_oHK(;r-}XZur2K6`|(?Th13yH@qJmn+)$q#|?(}qhpKV16ywl)u3_hx0?i1d52+J_~uX_ z0Js7_9{K@BZ^y+Cm(M3cSAod+3WxB{kX(WBwr9>$Tm?O8c&rAy^1OV?@NtzhmGjy& zn#WY0!?)AI&l=oQIiF%N7=F(1Sa~>Hr9W@@u*&&fRz-$K{B7rIbeG||!jx6`?$F_& zFE0tG^7vX%cu(ki-Ip&y7oa9zG(=y%3{3%{`|_31g}yYz2^{{~@P1#uF?<{`gWt#w ze{1*{t|wp*88&LV_Pyc#uKi$mbWOVQli@L}{cr{N*|0%RehKY{hxMrZDxk`{h<*Mo z^f&;FO1?7!qx6FANr7`Wdy+>l7va~)u`aTBCW=?;JL>>yT_pmlypbH?gmWPP=xXXz zpyjEU$KjP`&Oi`32YLNC%IJbuUf~EgH$1!|Z5DhXSmjoZ0w`woY^|#?4xD_!(_YahPIQw>7m+ThoHJ zjP4oE=Yj5-M)xY{3eR%h)w&lr+|9Q^>psijD-Bxr*>!X;40PuVXbuhM7(VF7xlV6X z*8Ny)+A85px5ViP0R6bkX$%j`??F1@%bhQSwpQ0^YfYWD*4AxnopVpn)_T)cQ=Yq5 zIydUJZgDC~k(mZ}VDQF{3;KAwmnsaN=_Fe&1-g2}Re%;~2e6;-^=S1AR%a52j z;e*Z)7@^zxT*)HE@(7JN!>dJLr3UuWeU3*bC zobNtCT~4@>I}Qutfp|^?f0w&$KxkbR_?dFVpNC=Br(R>X5TNd369HA;30zD!b)x_< z1+{nk!pLQ@Z>(4%Rb&sPiEN9$T5Eq|N7nU>b zi_|rPllnm2M>x^w8tiThbPX|me2pgt;4{vPO> zWOR8PrOEEMTGy#Ae?jmZt?M-R#6Z{Sb#HOJ`UTQuRhZWjQB?ZQjk$I<5{ zg-R7wbCy`@l2%1BWh`@7fN_fWtLNeK+>5|Oisa^hxqB&?SP_5dJiNkP3nr`R&0D~n z?`{B-Tf`q#2(NUn1(R3ApH2v0;BE$!U&Nn52w&*l0;Zto(c8dW;8y z2TW0sa}k(}-TT257xC90!k4&@fGH{BPalL=xjVrmi{wPS)O{9Ad67i(W$ue$niP$p z*yZjAV44>32Oq+#-A}=^QpJ3}UCd`_#Sfvg#eBMU+L}!{}2`>+S?mk(#G3YxsQV} z-oDy>8cam{^cwdCFuB^>8{Iu%j8Ct1_kzjS-oDO#3yksU_3pc13bnU4xgUWsKE1*H z42<#VX7@`lCEE2{+(TfDPj7Vj<8H>MH@UxoX`+hxxV)H80E_uGLox5(wQqQ*rYWw< zHO2K&F)xGKUz|~kIc4N=of^K`{RwVD4Bp`mz);{Jt?|lMm$dQ9oo)n-@ycCp9E^#< zyWMOsCI+{;1z_UZU-!6-SQCTW-BK{dU-!CacAIS-bCp#E?|qf>M0&W zVO~s%&mzSsH?JF)yl=X*FpBlsh2M5(Vs4Y4wL8oS;2rmK{3)1&ro!*KhjG&6)(q>f z!tc2!phCg>9GdstM_{DNo5fl21NV6_^{q(#r%qemkta~oPwv26gY*bRsVTiLsSMOq)DCEImIJe@_!;jmoAM&i7Mwyr3RbeO1R zI-iG*Zlug72r3op3$H+C1xh2`mTQ@+;V9fonL^QXJDg#~99Zbap2u{U7Q2rNd}Y@_ zF4Bj;HU~TVPrMW+K`3@AdZA+HvM;e!INGsmaSSPYG9)5H-qZ5KzuJovgz}%k#VYnA zj#jJ%+Csm+0Tvk*2MWz&DgX_mqdM1Kk8|C|=>-csZMp?0Jxt>;ksQVRJELm0V> zi5095QTnBiXoJe;W7s2izY8J8oE0j=#u$7|w+}HswsAhT5-4rrBid)B4`G-i_nZyS zSzQ734Pf?0mA1tpvV99?Zj0|wO%Gu0@j*$z_dW|zuKlgWfLHh;s%#9=9bGW2GTa-1 zY)+wHp+@As$p{HS9|p2Bgm+0wE-wXP)y=dF?JHIW4NPx9Oy3_;P~C)rU;w5pt^RYKG3U z`!TJENO!>f>xi7endiBve^N~bJi`}JW$#hJ^Jl{%QLqFEUp~_gE1SyTdZ8CiFF~&b zvL%IXW!+s(aTN3sAWx>ywzU4mfBQpx0LTX^G&clv_hKBS?tg*&kwVwfLoc1|+niT{ zAi&31brJ`7&xbgTrEXgwol@v!JV9T+#WCn`ApBWSQ}+(esju|$(bIv*}#iRz0*_9*sGCHle__Gr#SPGSZ|+CGl+o7;f$ zc58}T-$J7Uq9Hlye{vOy^ogPcJBwf;@CLr1Y8;`8ZhWb>H46LqKwS;xA)3=;G$xEu z|0IK+-+?Ae9P}~E9)GYYEdK+sWuMJ8g-YCo%J#y;Af3c~Oa}Hjq}{|lVbF_6rzLhG zs_ezQ+JqBd;heFTa6J%7>~%peqc^?8Y@k3(TCvTrpoehjj$&x=r|8;S-nwjSWuVMRM|)bpMB!P=#0$t zGXc*HL|CLsMaz_JNocqL(3JuFDo`Clr5oAP={up!x&!$AfecR=Rr(eUnb8w0^sNu8(y!^Alf#@cL+G%FkMvxX9;V7u?k)wAKxv~C!rwx( zPkS0sW_3Vmw*YA}?X;=NKK&t_&DL;~9v2{`uVRX~&&Wvv;j5Wv`iO*`D&>1w_MH20 zDqH^ov@U?fiKX3Og+2Ed*1iqUjw9j5F)Bav#x(5t1hU6RRr!V&0W9E#_;>xnq<93u zcLoB}lb?C0U`q9o%`jNZNt;!}l(cNu%0pRwd>X#h8>}R>%^Ln7WYRHiR$CyQ0<`gkmb$i%$;ZGisn=18nQAmgBtHxfOZ-m%|_Xp)$}O*92hsvX|0yJ{D~d@q`9survA;rRJlf~Y=HQk|4_vUZV^Gg1NqVsf~t&x zYTbS#43G;J-+28s5a9^x6PloEQLih6yI4aznZeI)j!6g~ZLGv$%ej>K!)gi{s|~P@ zKCW8IYcxk&ZMy&(jN&mqByFgcrL6j(bqYqnIu+PlA6G4}W7!m|ni3bHc!LjV^K{cI zsCbTbJpbGYfye$%=x%C4wgd|8g}}#uC)AYftg*i5xcnCaVFYfflg8XV)O5Xd1vQmG zpv)Iit)|X8m2c>u#QIE>(bI>L3>DQ{68g?P%vO-km%nCcO@PSUK#b={QVufzwUJ*C z7;pcFZQ&;bq{iitzWr}%)T$;wAy8mHsT*>o+ViNw6H)gk)ljNh+c#*pZJ&iP{0Wjw z;+X2aYTK0XVtYT}TtIwJ_n(!uyMv8)vaf@5_y4OTrWzV}j2zoLCqp=$1s&);Ycbd- z@acFemO3Ol;pLgRG`bVsn-QY3yn#QL9_w;1B)Z~N?1hw2-AJA%q)O+x(1F+G&|Xm7 zKrcE;be_d)NRK4ybe3g74_@*+%W9#A1X(&S`5owyP!{H~o%jS6b%#ZZZMM>VB7QL? zMbGr!fejJ7Bup2(;?V$){jZuS>f1+)PFPt|j}KMqoV$Ec7y}lwh7d!un3ydKhLX zyo91DZFwhcxwdkUSg8#eVU%~^{9gy`G@Y<j;18O=Y zt^_cP@&gZ{n3Khzdr-89m2Q$sC`#fpl%bc8k^C1JBsLhpl;1Z&Y`~Ww9whM*h^Eyb z-U88;1P6UOh=G2^K{h;o0ZImCfcOIh|5bA$+6LWvRDOkFeAh4-mDauVsEn6UIhh)qX`KDfI>zxyB?|a}5dViVVamb<;zl)x#L4&svrDI%{=Klq`4L#>6M5kjvQw{WpBhm!(kH8H425UK z(6JJi8~z)FkF{|nO5VU{0Gp@}GY1?4q8EuO5YtEu1hJCDC=j=hm;~Z=5F@E*1Tw8f zsz%^t&B#)kJr89axad-!K#X%p%4`~V&5wXOiGiA=fkLTaG-V(bf&2#&1~x|hsrU?_ zvH}=A;42VSBz^`lnFL>aJP*W3R{L9XxS&&WAa(&hfjOPKaaP~*BdZN#BTK;#!|4gd zXnHeB_TV#s6}PaVb3nYrhWMuZ-!)Xt_1g-7xuW4y$k%IM>s0?5m4~kZ{xMEJC5G)5d{4N}LFUrwe0ENSNP2&Rf5P;cY&x26&0PX)o5^hAY|Ft=u+0z+p$$_Ak9 zB9t|eGVK}xMi`){2JmXIsWN;FkR7OEcqoaXgngc2l(begg{EksuUFNSnW9yxqGl-K zh~08TBlF;zc1GB^s>3^#Slc`cu|xPsNTrrMty4>$)~O{=YhJNc2R_^g{fSCVapKmg zDDRT#wNkfK#coounl~GhV8w?Pqq7RN??k)?myt>E=y8*|n7p0xpOQTd=aOcd4FxOl zemgG`Q^EGF!j)spoM{M`f3wEzV6eF}|4P+&dx8yXq#DT=lL8*l)`10-Gsv6}?@ z{|SiWpJ|b*X15*i9ayRI83?KJ4hX5jRU)fklrBU&dAPL15n$S_H5*J(GF5b|DQcT4 z;zFDi`=p9!GoKh7FGWl#r)u`0jL$7jOO=g&7iD`9D>eKLN$U7lO2_XgV$@ulDzY)V z9|fsxS_Mv$niz^G^|X;{rE0Q`)SE`Cv#KdEQlF=EHA7KX=&FY?8i6cBk^gWCS-`Hl zp=48w@oRNZHEkfr^X@2-8*Y1dF|ZMXH9d`n<9!XE*V3@s*D!*qiP-;PM$tT9(Hp*^ zF$THRN0$1?B!k@QBe(j%?#qLGRWxl2B~2R6RI8TS5EqsZ#KwujmX3*uDiw@Gsx(74N~)|A<}X3ipT+9tq|`93Q#aM~V%y&ezt$Aj8WHA_m@VO0ksX^9TOR z#>d+D4C;N3PcR2%4a2nw$;ytF8UFla5b6fhZtmZQp{?p#bz@3?UY%Omb2)r>zyx|V_y`lL^@PRi*p|+@R zT-VOiH1bz(Fn0l~{M8#b{8N=jOqIWSW8Xhj`NmZFe|m!tm-ufCKGwz(c%n~LEpPN? z?ti8tm3-q8FNwY@O~wb?aqOI>d)(#T)EvEEckolZ1{VY|&on$}ge>z|Z;VygVr zwZH#Um3(xTCjZs7Ej41bHqE1>+AtaKR5QOoxGJ=C8`iHSjmF+3laI9A~Qh)q%53 zmH(Fm`B0Mo(($o2UWZyw;}bZr5gc@+?>Sc@9ZQU$ZZFjB zZ60FsxyfwseaG;&{TWVox5$XBt~~;kvYJH*%jE;h;v<@#2e+AQjulsP3Wl_NH5lsF z0n<+ft(b^1F0C69Ok$aaTkK2FTBzxtlMzl z>bjO_*~b(;Dji2wwO#_uMU{xC@q7v%D*qCeSsw?bcpgc09s1%B`U8h7JRXtdFNsd4 zDHu;P(rIutA7)qK8uSv?Z)^^UgS~2b^hP*q@Fw87z^4Hng^SLc7N1qV3TXK4fVhk| zA*TjEg#ye)Dh*mF`=!Wwm_hr0i}qdyoWZ8>A}+KINW-Boz!PZb$o)X&bgQDi1&|y3 zE{bwNe8jf#MD1G{!||vx{0l&ItuI?cnlZ1iNR;jVQ zW`sdHX(V;J9B+UczseH7%83R!)kn&Fh}mH5j>6=Fu0P zU-g)i!l@#pLbpMU(}TL>j&sHiRQire9cRwlR663g8s*HR4USV^Wj#viGljJZRo0Va z7YJ+TtE|h}?o9Z-Qh^!~i>QXg1AP`qn9d(*1-~=pbtyn1o^|{STLyhqcm! z2Lq*_AF1?(xdzt&10qov>6r7Pd`Jsc>_mO-|x ze28YtDBG5(&8eWDLRLC}T-&K<^#}hQm^|Cbw)TU_A2wpJa&jyQ7%Nj1+)qPt4WFS3 z7EnW;;p3{HGx2=G$5g>jWRmDB=GkzvCyM@*}4ogSE0BB06{NW}^3M4IL}ZLKrm z)^0fQ@*Jm~RSu$nFNQeBSexN=Cm(0F*3|*OM(204qkt;sEDlL0i}MA#*~bb)_eIoY zJAEx?q$-$D28n*!F3bf+SAT1Cplg7!%cETbt^NQC%bhV+YjkidCL!5-?~JubD|w;D zIo_H8#+FxYoN?9^Fiuew9WvgU2}ZyC;hbQd3P!)?;7qXQfQicsHO@q90hla#`NNrH zEdo91#R=m! zeG&TWO9rd@%c07uuQOPA&Z_{@8GraL7sq1R){$1-0OwSF+162Cwsq8Bg0+iXU$%AB zmu(&OWm`vm+162Cwsq9k+d4wr){!>&9Vqr3YA!hyqhvMRk8$_VEBGo?)$DVBst?UYrR27k$n%2IbPV`rbEeJ3 zmQo?{pnWLYQ%5=0zU1PTu8Onn=!f)9tG!OKx(Z5)n^hVIq| zcB=|amq|Mt*v>+-(#s9hwgc?Z5j4|c7nE4nvU2VyuqV)I*U^A6U|XIE^@AYa1b8zn zWA9<*#`NF{Amw1J9hGg#Lb{P()~XsMH=?A~5CcIlF&#C6vE6*+*iMo`ma)YkW?{UV z|4GBf^npDeq9Q}b+W4L4_i+sS_!OGZeH_C+enM9IIEH3Acofv=3)DRmOpE$-+3|0n zV`V6B@f-U&t|^q9M|L97@nqMLJxKHfDtQWQYgubeVB?|H2hVNMjOaw7RmY);Z_vaX zFy-*i43z;}PJ8U&N0g6-M)(0=%HYR_@EbHAo|}dMXB(=;ZxSdC|#1_zymPrhO zOfW7N9XT%R{c&kvp7El4vbM2czN~EytF~BZho^Ds$Y_g&c6d6;%(hr)hi8z?YKw(- zcqYkuZL!b}&mx)K77Ok0NhEXH_GqudCzFh{#X>uL3Q4aW7uw-dNkcIf+TppRE8AkB z9lo4oRy!`V!>dUbwBtfMyoPjsTQ0Q2Ye^TjlEt_@@$DutZ zxb_Fow+^afF-G@QknQEbxN5%(2fWLG>BCWP=HsXrx-TMVc;U)IZT{O)hFMWB36aZ? z*%HmN*Wt3)Dd`Ovv+Q-+7NevB!GQIyyldrf1?*JLl9JjhV23MUr{j49{%!?qmc9;` zzHT$zA>+ym z^&-bo8MF*KwJDU^qGj+Qlw}^O1U#gUmZAFtEyJ{y(@`%noO>&vWx@tj8mzTUY>&U0 zA5+VuI$9<-0Hkd>QER!HVpFnF3@x);H^F{zt>uhG)WYBMh|H;@WiC^2Xf5-!mbR!D znLkErIgcCm4rndQpTghx&`~2*WJMh<=gUf3{IXJOX-B_YaGln2#Y|Y%kP8VXvMz$Z zncUT5f9(NNc%WYw3Y{ zkvp297=C$hW(9sKQfqnW3Tk;D1(ApAXnBN5y|tD{jV%;=j2ok&<;5SH;agL!W%mL6 zjrSjdmjLQ0+4EGOu}WnjM(7Hj&;E96oL+R~ zpFL2VWkpJ?LuhfRi;3KdB&_xzvL`o!Km&`XwuM%+XOM4bcogQyxtO$K5YCaHD-}@X zeoyPmEac9m?h)4L#`wlo>#ni3Q@1!{q}GMoylnBtD8r|zY;nhE!@DY5{4vJxI6rmU z$IFUdw>?fkl{*G)MaEm>&`RFY$Z1v%hWeH?TsdSWIo%?y3S>fYdr!ct3XbcdDc!axdjsQ^Q~vW6c$M6o@w!i+Dq~ofeWlxKqm`M zz7{Iavi5-~FPOm7!xGZq*L`|ig)~Us$P{w zO>S7Pr)EuVSg)6`NMa;uaJ}9dHED3YKAJVDV!ggv*rbZ}`fJpr!Sx1c)TF`n25J;T zAQvHT@Er6><^xZzEXrXTTyN-f-Bn40o8w7W&-*>->T<2cWRCUp3~u>dJzvnEs~2ct zzpEE%*6-@Y!m_KsmZITR8uj~jsYd<2U9M4+2G?7o*`PC5oB#`TXVwu?&Q(e1T+h1) zjGLsv{Z@D8nf>^y$L(3I#qZ2>n)N&Lys$xMc4^e4!S!C$tVx6G={Xx|R3#0rC-bz! zzBNaDd#{Qxr@nY5*w=JjlLpt@t67r<*Lz*FLEqkJ27`6q-Xx?Pror{zYJlP_$J1$W ze@jQO%=+*-V4$#SLDlvY7_g%P@R_ z%03(GT`$YXXQ^za!S(8C9(~Sc8eA{O@aZa>X>h$4ylg&y|C8XV6Wb=%{t94OOmj~7touFZwy304{ajDt>t zn;nz3&#-4i<>&-KKzRG4ATyMVN^Hes|;Cc%*k1w6HZD$$Yx9w~rAJ}$| zby;BBA^}xyW7>AEb)L3Or@_5T+qT|X2O^tkaJ?(FE~J{xW*S`YDxh$8tp)(#H=PFeBtF%3 zyvOjv)xK?yYhARBX>h%rMmKC@8eH!w!^5vkgX=wQc#J92;Cjy(9)4vST<_!ntGNO zwwYE@w;i!%$%C2C=<@8tfv$7`RqhT(dDQ-%x@=FU!Og(jRL}N`>}i3nVw-{(UO`Ii zO9LdK5v0K_?lVkz4K#}jH&rC<2Li#;BL&Nj5G=P}3j`}P!nU*z>f21ZSbxrRnA%W` zs?RjIUL!H1KGWcOmC};-Q)5w}a+wC#Yhp7oBmAV(;2zJuS>6!42Z(H@FY$)f_0urB zF+i|M#XEKIqvr zdv4Iubkouzc5Q||UALsu;8wvIu=*^!F^FuY!S&7#n#yJxTyJ5jt+nj;IflogQ`$b) z@Il*)?e~JVmk6kGnFiNeYQL)6)@g8G(rvG`?*&oJG`QXsMi;utM5o?5!y~s5)8KmR z4e!DYNQ3KLX?V=|V#`&A4{W*G9t-8#c_$FvdN5{9Rwj??Z8QzbM?+qXH@&}vQFm&5L3aD~jo&!JG z-{`h=8r&~*+mX;~AoPfMA(?l05=eBU8{Qw0sNwzSh#B6Gjts*Gwq%ADK)JRhOF)&o zI0;+og-!whKj<{L>v7eDA1XuVg3z`!HoAOUni$@PxVE*GfGU@1aJ|-{pS7(z4KBAzz}5kw|Ik)O$3UaXM8_b*`q43@Zc9T$ zcLyyEGcCo~((uq`0Pu=VgS$w#bYf@<2pt_$f~ItIOii^V(J{^Ness(*e9+68p&}^L zy__YW%4Hf{@1#%+0NU1Ra3h#c(93f}-=b8H$YP_*ACV=7_eW%@;r-}XW_Uk3mK#2> zWkqORV9WUes$8bQ^;U*1)VAm}xI45h*MzPCp>5e{bosViYk1$5>kRKl$MuHyqhpid z{ph&C@P2e`F??X_jiFLBuKjkCfGU@1aJ`#Dxd3nl)@g8;VjYaj=M$kBAhMYT*V`G| z0W~%rxnwg9uJ@$ju^MC=T<WO`<-s(# z-t&gXLk#AQ^>>X;RrW3JiH=p9UZh) z%rv-O3&X=JOoQvSG(6lQUTtM~-Ybc1ZJfIU+u90<`vb;8J7+U(b3B~}_d43$Ej3Xv^rH;XDxNo@sP54X!uKxn1klX>g|_uF;RPoWUS;KhCbBdtsnEdq8t& zILGioKhAY>P+9k5v1yBGaJ?l?8UXY|r@>{SMYMIf!<3D>t<`nfT2rU3wRPKC=P-|o zZfm`1i)nDZE1fyIEu9AU1T1*b)~!x25ZT7a>#1y} z!S(JmJZ>$S2G_ew^Gt)Qhi{w1#E;sPdjv$Nl%nQ#=Y4I8PJ??uo3hK4&MW|MxlV)2B#dyw zL5I&Ebz7fnUA)~A-Cr6$=-1cI_kr$jjP9v?5b&+@Z|b%@od$Oqbz7ctXHqv4hkBMP z%bL{flr32twVfdW@x&M_XQZp?fm+a|)8OvWy0YCJfv%jox^msC0cu@&M%UgXbmhCN zsLSzm8r&j`9{ODFDiGSP3Rg}|roq)?*Vz3m(A7jhmCH1^UQ_n~b=jUygFB77Y_Eem zDA3i>mFbLWaJ8<^ZX1Bwt}X(q-2UuiSC`LI&_|sHmq`}6oRM^m*-V4$4b*+aGSKK6 z>@E&;4KaOW8eDIvdxqAf)8PK0b&YpF1)+7FP*>MP_r*ZhB%_OIaJ|XyV_KI^gUej} zuaBE729sC7G`QXc z?rbpm1xzaHUFgmSQ&7M(xZXwXLNJ8|Oe*UA%UuGdsKB`h%*E~sFvSH-gX>-5UIeD3 zfEh-;Rqmx=lCs;$yVP9^ro2F+`7(C{m?i~GH|kyP-U+5@0n^}mtKIEjTB$-l-!9}c zGUyAOdW(XQX(J`TqC^hWn-Fvh1h zxi5feq6+!AypT@-3;8v2A@AO`Z+NGsDXz*j#r07kFN4}&oKXuoW#lpqu6MKhG~9$3 z)M;>E!9g<{Sb_a!ENrp!Nj${?s2~WV`6Z-`z;vb zuY27e!I&7_;r1D3f4l?L6z?`P#g$qiFaNq4 zuM~xxIyK7)CU+ngK99QxFkQ~*9!5CM+=JG2@mSpJ{NtcilZ0f*fun_ug}lLWTNFgX_KTUIclS%QU#&2ktsBB`pwq zR(kVaKqqEl!KV^B6odsI+mW;h+{PI9FAFueK^)je2imu;$$v{5_1rJx%hevjYT`rh?0+S zakHac^UBdy2goc*EP?GRaUqUYVl|F-f?Flgu9R<;^82LxaVejR4llJ6i|}Weoj6}} zmul{F_;jh0_#S_jIf?&i&VhTujmG@3G%Ya!f0m^s=3vm4MiLA0XIUh1DTZ}vdSX5P zEW_LMpTNlIxY_VcNjYq^qf?)yy%RA{FG(!7Xz!J1&`Mka+D@#)F_gGY%5TBZN^Fzz zhot-l3>@se9e-f&y_$PebIc+Rd%wURSonkHe%D-o1O)6Y(e@sr?d`7Z?WOGO#8d%Xw_rpKuS3u@k zuGA7+akLVT;Akga#4(gOfTNQ*h@+eMFOF%6G{j*zk%wa>QO=l5@EJ~eA_vE4q7ja< z#48Ra&O|lnj6@BNnTc{3pOvVO>AGIx4a_%764@wOqMWy3L39h>IV#zY5-WP^e`(M6 zFlR~PV3JnV!-Qld&H!yEHkHz?5Im5c zc$CALcn6(!5xa!*OHR8`X@?C*6M`LTJ11vb-cs7T1K)~7d3{=C+I!$Fk=0J7MZm=-c6w#ElSqv zp_C~^Osj-stxibR>V#yiPUx)F4zpIr`;_ZilC^pXYn_T-sKmMKOJWs{cH&wbL&{;+ z>iCf3wY+4lzK!yqAv#n-vQ{T_)@p}YtK*~or6nb6^&U!&grJqsS*xAKs1_f$L(53k z>OUycSo$Sds}qv7I-#>xJIq=gpR!-eOV(=Utw>1L>V#yiP81=&?1au*?J#R~{NxB^ z;1kJOJ)H7wF*qurvsOFIS{*;5qn44Z)$=J+A|B9Ls~u*ojxXURqSE{Lh1Ar(i>-8TxYFbh|;AggjuWOI&1Y6D7`vBDw(x9E?KL&>CoB^bPXBZccPMkTZO=oE20hvsT9?YqhAq2=HaTh^k=L>bTBY zy#=MWrH~TFmCjoI7)syrk#dHt3{5$MQHE4iyiP-O*6J@I`M*G#Cxi(NX049vtks!E zVSR;I}tFK1sO+KQ1R>7>*ahnYB8uvsUj0^qLQ= z3TCa2>#WuPM(LL+gd57^I&1Y|l)6XzKB!>U>bTBYU4+txDP$#2h9{fiQfswEX{QwO z3Z1UARu4w$7#}fV?s6uPtku%_*?^ZGAyUq1QB^W)b^Mw0;0%%50GTaE$f-(Zt&U69 zY7uz^@N;!Un6)}CS*u0leZZgkBC7H|Dv+$zg8mM~ZsB*nl3A|_C2O^yF9X?^LYcKXE?KJu{R+tUDU?~OwYr?G6amiY}(uc8L zb9lq!IZF{4>1?1x-c`z|{s=M&c~>bR?nBZ7YoMJ1EX;8@7OMMPE6|Ga-}NnzY-L@)WjO;Lr}A zM&wlEt8ltxwyXqt8`yy;8|{PToMKcZUtZ5_n+*xP-=wV50G}O*NTZdJEQqwb9wJm? ztpS}1h6x^1i;J*H!WYCMB(4|r* ziO99aw`m8+qMG6lDF4rw>Z6x`M#(rL+^S)dp5(iu)N1-G?? zi|U5!K!J4SjVRkxpG;n zv95SVAA&2js?3j}hNR%`!T`Ap^{x);vYM)73T{hMaPI(XZ3p~VAi^S5AzE|_?$-c) z6u`d#Eq_sDn1b7yzLUy+0AJULp*dDTNKO6SSZ zYF!mBLA^Nw)~&3z?IrR%z_)HQOWA#iw7ubW6bgwGxd4~oP*rF*rSAk9lFiVq+aTq| zacmAsPp^V}l_>o_P+G+a;uwCJsUdYVPs)%w1}`JxQ^#`If2}R=ma@E?SblT`D%zb; zY3g4qwoY}qb*f@(so0(k^?-4wwD(`vT!NAqxDHhJ^>HA2g2*2OVlapfB*uUk1EM24 zGaJJAudHJ_G(`C`6vzefH3<(yd@Km|ss)IS9cx$V-eDS8slsd*Qe`Lzslp*-75wYO zDc-()8`>%7EVQu#)OQ__9h1XL;y4I)ncSUHJ5b?LuwDCM#^@&Fx0Pj|qOALwP`VwJ zX9KghUjVAZN)#0y4|$dyy9QiV)ipQ{KpDKlDCmb4utZb#gAcIA4iudNw5MNQwG$LqfymtII|Z5 z4u5+w$BwEV4U!X8wJt(-9aYWtC`OE8tyT3Yrf8NaLd|&~S#wdUXt9yH%oL&GrjD3& zpzBE~!u!H6_u~7)?T)gj+6`3+fp<=Fn@Q@~rL`Vde>ooZFL z#>21M;8z_PpYbF-8f9&{)Uf}4HK9CZFJo*=; zl|kP83)0yjhw37|M*yLN#a-VW>8^Rcb75X5E@|x1mqUCLuTUG?fI85%Rv#C^>@FRW zlwyDG1>1E$y4*KEA7v+VwzOAI(hgX-0}>xVLV7J+vl9^Ui#sDT4xo1Ut0h-aau6_) z6z)85)fYmdE9`y*W^hOmE9+6j;bFo=8KOTpMD{#LGw~pM`MW>}jH}R71S`c>k58k5 z4yyWoqcanKwa(tpnTq0`D}qW$$I{${60~oERtEeasfU1PE=krhIGd@;<8i1(ajUy?Vx!OS>q473K8J0Vy9AO2_7yYNmpx zk>Ax8hA|(Sa<7Yc%@QMF{6V9y}DGyPz1yNLk9tj?->m?`RF zieU6~6tU?UQiP^g22I-wB%o4#J`J*r)$?>yq4eK_SlthZbI*FMS>pG7Q+9i*Y`{U3 z(Wu@EU0}NsqsxLe-OvlQ&fkH&nXnJHg6vGL)HZ$(RUN8poxeBYwCXacic-J9H}MHj ze+cLAAi0=X7U!&)C>(q$UT5Y56LtJVaQLYd%{>lo2-hQH(1u*MO0DVL(8y;fOP>tl z9S{vbXt9|PbHLbT)+%4DwJ+8?5IfTsYh*DGj%XX>i=7gP@rNZuTebu%lDb^dhC*VNq&wD; zUQ|nZlaXGfrCq$leYm#Om(-HI6|(futs;wyuAb59q5F-R-2$1p+zoB0Rr_&M`!m1x zpK^||b}@#J9ZXh9D;CyUVN_n|tNi0wReh;Zc9Sl|4-wQFdrl2BVy9mt)w9i}-X{VD z&6n4z%}Io{|MY9iQbtU<-_$PcLB9mGJJzbrGl;Xza1p5qrAMt=l9SA3QO|Vq&^w+@ zlwaw~$7;);Ra@SVVO7o3iwsZeS`U zd+JC?&#YZ(TkT5v`eNjV`SMw{<)1l1p55;Zc{=-Kkv}4Y2N_jY_^NVhtJ>$QQq?1k zj=Oywsp007D1G*I6xP;p$k%~biAAPLg|T= zUI}b0n6y%y6qr)&O5A8b#V|Ge?X{Rv-{hrbM2}V~YuZ(K2$M0QM{A@7Bbhm(M;nzj zgJjkSBn`=$NwVIE9_>`tERxwHkTfLgB$7EJdbC$rCzFhfK+=$`Q%HI>Od67PDrqQ2 z(vYmVq$@`tX-L-PB(rLmG$d;^>4F+24ar(VI)4O{hGeZJT{wbCL$a{NCKX?rV{(p! zoiw;H@+-u`$c2V+HhET#Oud&bJ5|yWS3n{<4~HdD*{Kqhohnh;sS;fuL$guYsS=f) zDpA>~5|y1QQQ4^ym7OY4*{Kqhohnh;sS=f)Dp9>tCG@zB;O^8I&7{jtm9(zCP!g4$ zDpA>~5|y1QQQ4^ym7OY4*{Kqhohnh;sS=f)Dp9>tC8~F-MDYXZ4y;CJ>cB+K9QzdQO^|V)Zs-#W*k@m_?m8k4g ziONou=p_)bqq0*aDmzu8vQs50J5{2xQzfc*szmipm8jmS64g6Zq95TDTuMuiRzsyQN2?os&}eH%}$jNcdDc<9|{}OWv5Eo`Q;(l+dGfrDmzu8 zvQs6hcdCST;*3hWSkj_dX|hvg2jyj_N_1-k3)`sdREf$?m8k4giONousO(gU%1)K2 z>{N-$PL-(aREf$?m8k4giONousO(gU%1)K2>{N-$PL-(aREcI|6qcwEcdDdqX$c$B z_oKv0yS37RJ>MgUmqZUH@h2)fRibBrwxhCBB`P~rqOwyZDmzu8vQs50J5{2xQza@p zRick#IHOV7sS?#YRYKgUlJ@WuXfgg8oL88(>pHZU!JR5;yXicY5l35TFTD)X$>2_v zv^_K`lEIxSX)m)pmcgAWX|M1k%F3uhN!qInlw9BD(xOZjc`lwThPpY!Y6_M^0J&Z`_0KNt_vU%YAK{F$pLFS!U zjj@sMjbhc;K{zVk8%5=Nqo{mu6qWCdqVl~_RK7Qg%J)XmDu{=p^D(POl;pUJ4Q4Wt z{C+*rWvk8axbkH%H@|hvgKV{cmYG4Y+F^k#l+hIGMjBbsKbBd|zhb--(>z`XUPepBISm zVxY1_%aR;lF+3t6!SnE` zM}lpS!rxFB)#Cj~HhcsX%R=!1n{d)-GX|4X#S3W0P@0hpB`GCaulAzOethbYQ>E|s zh0w4YA^If>zYBn}RRo5+@Fg|y)sYN*Os!6R0M_t_v`SIfI0bZOnjZKIR?hvQ9(kya34>0O|PH!#L6e>k=RveN=)|M`)u2opJm< zFxc7#d}km-Z)S^2v#w-!#(jvkcotgwA;Xzh`XeIQ;@_-qI1J;P;mCTHf|H{7q~uiA z`)uxng}zyh05|nTRMrwUG~sS^M-=n`GRQ}@EsgroNfWc#<4J&~`><;CF+v;F7Iye{e9X#t`A1m$3Z$b4L8$0|aI{qDXZ*={ z?S7O)=Ji%^%VEk)1EHel<7h>PLBx*U0Xl>Q6aHizcw5WAbH^myW2Qs0ujqUhuCSu@ zM1CTA6^b%Fx)Ys^5?6)pgmlKo>5xxkWgfi3|dYDdzsjQKDuvlGK9D`Q19=*}$9)opcQd7%m|hxW{_7qhKoX7^Xd;=7S3^k2Zb z$5LKpjAL6>^sAH61HQ@Z!SYB(Am8Y@6EPyGuBe3 z56cU+4SiW&qC&5s)y#hXMdc!UY39IfXnQk_;FO*@h$P8q zSQWa5_6|7*MMYWXWe%@^t17Yd%-~dzIYJU46+bo-bPdO2gH^m}BAAh6ZncV^m<(nV znFp=n-PK@5(+e+H#iPj_NB1AJijQRn#UrLcs z5nf0tIq!zXgP-n$BvgbGbtNxNp|inX;)AT&1Uctr5LG3o{m|7YyU`br+LgR=g|?&Y zS-;$`*oh^ukm`9w2<->|u`eaHn>u|E??=mp!;51xJtt(%AJzOUWw+!Y;foQ@Pxf%D z2qK;Ek)Dxgwv6(_DW$6lsUn$9sqV4|8t<9#xh7i|#X2<)l(YLI_DwNuUT} z4w8f+AR#98q#tCP|p#@QC6bD+n)qiU% z;zT>X-*4@6D#5?^-Fv_Hz4tC3Ikl#}_S$Q&J)Cp)*}DRAGrU9ul*3-<6ppFeaifH( z1s;Ajg7G;1`g%?~j;hF?hkaNFliaQrFJ8wZMIk&gl=<}sr5_GZ6a=sK=X;FVV7SHZ ze;dt{xxlN)36X=GUTg!!s|rA8r*amg^Uw9L8;Gqcbb0%P=VAW^Yyf;B$*d;jFW`+f z^EIW-rJqjhTo>yv7*z=~M%3f21TwG!74Z{{GGUZC_*@uO#MrnVJXQQI7;{nVt3e)w zcTFpC<*ThKRs6Bb+U>HIlf~zcCC6M&O9B`PZG%~}98gm5*bP%B_~1h%4kJ2?Sfh_2 z%c2|r?*bUo2Y^vE^bFXN26-`W+K>x?8dbv>pm;gTzTKP|1zWqc0IK%jPb!ab@iR0P ztfG7Hu6#BJpPutktbC-f;Pge1rIjnhcD!*Y9s&;Ml^caqWt6Z`WQ=x`+@h2Ctg(3V zxQC^;#(3(vxt@#I|$H1EuL5EXPFoA-st zN&I@%5>!VK8}%I!Q^MTlF>k!WW4=J2kbv!P03{uBLs?3v0 zUEt=}6@VH@>+KP^djVoTeU2wJ#gke@sbWezjrh3<{6TnK%mCrDc2;oH3|4#7v_X7I z+caO5w;li3egPr8t;EZ8WCV|VTv3Zubq+Nqs*z*9OwCtnjKtxJ=&S_9l z^cYB2P>g-`Zihi$-AM0&j@SRvT+G$_vRZK-FGfy`z?lL!a}^;<&MhcA)*C9$8{eK z^lwD1rmf2+6eF9npr&wZ#nn*@Uyf;~cP*>b#y`biWlLh+Eqs~;;6 zG)}Idy>0~+Np+(8QWNP{{(~o!nQt^9Z*gu6%5={oD$S1KF=H5l!e=o7;(~4flt~}3 zured`t4!WS9rW-QRT*yr%!$U55vW42jONe5oR`+h#g`+uf=Y<#w``MS^F*uZ-8JR# zUAaL=?14z}g;2rh8;`_@Kr2x3n-cE#N~lVyQUN?P9^sG-iS;b$BY|rT@7OfSSl&Fv7?L0kE$xy9tLU0e?`qQ+`Ex*BzD zH@&;sPuJlMP02urbkc!x%D(;6xPkCK1Hj3LQSnq2qC|8o=5sEbM1a7T%H5 z3*_$upHcUAYrbZ^1{TBY-@=mVL-A42=(BW`NlY5k+N9ItCY5{)LAEL8vx2@V<4v-; z$@mEjbWre3DRl6uTs+>oqtFFUx$(AHLTD;T<&3vWBy<)4og$srr4nzG5o?!;U{&W) zP=C3>n}lXa6&IIk>+cpzr7e~4Nsl`iSb-aUQ`;BEjfb(kKR0hR<|9FWG4@NSnGkMe z>bbZC|5apXB|@E8%}7}W7h;CtXuBqLr1ynww|)gRbR9}~|k2C+(};2OUc_@o{5 z)>o1U!{kIx`1ubODD!LMD`Y(EIB2v(h}FLUW6D-tunENc)<}be(tPg%TX(^goVUt9 z7U?IWkRqJ8zC;a`oNDr4SaW0Kaz^yFzGtTdT>G6S+T;1mAtd&e!#zzmPGPlFR zLf}U8R%m$#fAMHaJPY>U0)7wh*@KzpYfK4p@g9&_N&Aq%t$>neKx12OsSrLcG25Ci zgRx8U_y*!uR;xTtgECzqZB16dWyFV$lVrSqxd(VbKGalA=jhwcWFPtph*kSpYZ|xD z2L2Q)EKT?s#6MsKX?!4Yx#wzc?m_x#z{`0zk}l#41jU?FqvsK=Te?)48Ror^-VVHy zT`7yvz!G&Z_u?(kFm|P?k~RMtI2$zQV{nGB=FO(j1*A=9#iP<$qrX7T1Y&kK?M$~u z2QTrsiWZaG!|Vv|FxIz{zP=kcJhjOjXpSU@Gg9g2Z(?E*=>ZWwp@PT)h{&yk*)&O{ z_DU8UG){q(%`66*TWA0keFm}c zgwsIhTVulQXIyg-labxi0n78~BN*J|Inlb2YDOD0(&X63AUQANGK(*egR41Qrt+PH zyce0R=I~gG@8KBEHBt$rCZQKkJqAe4+{_5kcs^!I-1{qQ=DMmNtQmkEx~>Wh(k(({Uolx|GwCI8HMom zI0}Kl)8nB&B!y4P0QqJRQ4#WL%il8{z6!~!t#K!3dzf)ki1L^$;+gWyi5wo%cM}Nmq`ib-Jqe3Z8&SkLix`?l0O9C ztTWmBB{#xAXFXv%xsvn^8GxPS{}4XE2yif&GZ^Or8kmxN1>ucDL2sKJqs*pqz~w2Q z626EshLQ3)m0nE5G*Uw3Y?k5~sx5yLY?_fukeRikb3t?f3$cJixljZgohTdRG|Do^ z_S*pr*7)fjZn{)!9P_+{@9oor&NW+r-3*!Jp#wp_b~lwKUqlP2c2go|a!8t`=cCzwbZN-xJQ!{a@=w$` zJqkv;gbXi&l`go?F0kPc8 zR5^hPaPPCWi=1OrMqlzKH!^Pt4yVdQec`TjZRW?&@gO`<3h69#>dvoOya|9atfqZy zRpxQ<4}d@49C3&K@Z3uK=wxS zQy9v05ieyCkHNZ*ztD4+l9SSi`dZew6ew*U2DIbb!ewAC0NU*+4AaHCoFbb+>z+!H zD~L|TT}&4o@3e)vegY)-96DwzTa?w*ye9V-qD?O#FRSVBn%wC`x4kRqH>G-9`gC=V6R_l7bo^a#g4CN7x)(y3xnuBsAvjlo!|;NA z+0#I?(f#(E?=oG6%A5|zki$*}PR7jALV_y$iUcaVd5y~4?GndmqTDj8%*R1}3k9tes=kqi z6_TXaJ}_bFMxBww0S~AK-){QHYCJ+Y1Ob|Io0bq$FjE%=Fr?>E@Y$YVq0jmQ?zG}b z*#pqQ(h;#*B%TuG+Fhlwia(E2Rc~toY9!CN5F9JuM5Lk&rBPKE)-t4QDo%CH!}hntKfkaT2H>+awXl#91D0Y@H)n2QvHrTR7o%Xz#RPUNSLgaqe?7o*mrc(Ho zrV~|tw*s$maTa~At7EOuQ0A9gjLm!%%xV~SmoV`ZWftx5SyS^_$q@dx7RFQ7%y(Ty ze-+u^HKyl3AhQ_yB<-zkMy!Q=OfVDcING<##{@I6o?vo5CYXr}2&Uv?f|=Mrux&mj zn28GsrsiXUnYf5xyL?PA6VD*%i4vZk3)g!>%tg?_*up^VP4qLKP{W;f7Sk0Pf$0?I&%uxfLWr7||p!1+z zc;Ye-#;8Ac!BtN|pRU$Z(CtaWS8okK2jZT^>z>T34+-{8V{;cS>UEO#ak$6H#3aI- zx5_bXPS#?f$dXAprp@WPjugFQQjTeJx@{GTESa>qWYQ_xNs3-FDJQl$#SaNZ=D7CC z9LSW91jYUa*(Ua!Oz=Cjt;Aj^mOipAaR7!btdWFR;=oM=xn?qP)5Gd}M$f2Jh(WZxgigEsIy!1iOnfzcm z@~bi)gOEzLLG@1+#7;hC5|C;^oa8kWn<+>zW$LIZ<)0-;O3ElAvjs^@?gfAP=NQZ; zoHBKMrSi`;m`zr4=^SukB9@E2Xpmjo3z*w!##4Y(?Vy|{cO_)o*}=i9@SDb6k%L31 z%Z}pGo?pZUht`1Ap4(UkhmoaElM4=?1~RnBX>uIeprxEM&-7#6;F^lxXqo(nxRy$- zt=(oqkknk<;YnX)WhWq?S9F z$WY_!qen}%e#S$63J zT8o?}$M3&UqH7M}H=PG$1+V>$mh1M$wQSc~c$!>r$DgzoIZdt~S_`z?nT6kUo~#wz z^&2gB*!3|l0nWeg8DSMY(JW;5zIDh03GIafu4@W>k#H?avc^B@8sejMx-r9jd!3T zB8{=LFjZTgCKt>x{;GBB)8uw&-BXPX)Gf}KrgdT8+z#T6Y8Usb4&sjKF78tu#2+(U z9DRk(dzLW}%5>hdg{j)|G`Zj$qbC?`HU#x)a?8;Nrbth6wn11QFBx27oCm~~QzC=s z80&#Ja@b>Vsc|8YV2ZS|Wd^5!DRT5;u+i88Bu!3G3@$f#h(K5lLJY1jwgbsZVFa!; zI3tWE^EA2ODq|;*++?067d+Rv6G)F_?&KUi&$tIjo*Wh!Tx~oJBtMy_$pzOKhk%So z=4o=lwFVa?)~FDB#t=KU5c{PNyOj`og%BHch;1^&CKY0f2r;5V49F0^rsm#%c)AHS zGMpr1TPDDMRthr`Vkd0HLm~$(X6O-*0B+0E%A*O*|&oI|IOZ&p+WtTm)^TFG-OI5^8G)0@5<0@E{)fF zSBB>ESl|D%_pS_WoCBZgy(>eT3TUr<5%53SyE1fH5Hi?|Ggph0fD^SBBi-i(dqU{z{|t-jyL4 zyY$|bq5W(`DbW!~6gt2_(R){hUT2W&y(>cp>0oc~$~HY;X7T>}-j$vCML>QKFEaQ= zKzsQjpdC64<1@(rh`%mm=AH^tF6pXk@~AgJ?wXP*KW&%rr`yy0kXXJ5ki@x2(~=NV zWSiOBKVSlw+I1AvBym{jTssO2&mr1(%#Cim9bJ2EH z+bR0>pkbz%W5G18z~!nIsbV}~YrE!Cq(DIwq%4to5E75XrFycIZPzuOis7C)nJG%7 z-tr`JX&8b+o*uUwm5Wy~|4+8CYFEzkbutBMbWKF-#wkL`PF zkoH5Kves+C2!vHy-ZO0wblg%a?G*Yg1*&pOasYNZtr_VuPbg$)Cj1pIX&rt-L@ zR+?<7^)Aqkp!M{axu1Zdayn%|LblZ6U5POg>`8GE$ux&sYNg4RT2x|iW4A?~i0Z>F zwbJyKTI)c)#N*^ngg%wSEw$2QOD#!!E7*5>BC6Y4cr=_QTWU#MJr?I6BA=uqxI)0R z3o~ItlnaXO0b=$kq}xR#8{Z(&4@^i*X-=_lxQ%oN{0S%bIJho*kg)rJRUBt`X6hV% zBVx-pB4TbO*t35lvKm!v%QqtXkgLIS)7Jf-hH8?FZTT3TeK_Ul(F(0KXAQmv2M@i2M}%X+|Eu5lNSCM5v)V z7=7Z*0sKZJUA_?+0pi#eMhWwjZ$xH-$fMr0x<33yBwc?avJBL7TR8kiBwc?aas{YY z#W^|rMkHOn5s_HG8=S{Ht^}u!&_4V|Bwc?avLE~p;xhDRuDCRZ--x8kHzLxPeh--h zI6$lukzDa_4!;pemv2Ov&gcZ0UMI<^9DXB`F5ifVS*2i)_e4|Gn0#$TuRQ_Cb%MRVx2(R4HrJjj}}h z5fFOi<)By082z_)h=Kci$)OBgrvmVRy()Sq(X9d@CWtquyNo zM|yx;)ebVU9c3_wLy1slR+=$GeLZyV)Fx)a76}4`6(BK_<>S!|YGcQTA&PH3$66glT5+!!Udu5=Qr7x@HcNl+iPgohj9e zX$RrKl2$xu4j~*YI&+>fhZ0Ot_8urPhYf_9LdP8WeHC8JQ6(L2mQqHE_$Y$5vQI$3 z9DNBy`d6OEH9+Q+=8lm6fLTprTUOCG$^g&goWPDg!lKr)6$GQRP`PFuD=sZsbqC;j zCJjfwXW9i10M07-bt>Qn(zAR8&rAfeQ1tu6|K=GFgOlqk=!t4F7e5AMgs*`8hJBG z#a&I#Exv-U=;rf@?D7>nI2XtTF9W&XSFnR6xX?ia?(q#eB?jbS_JU9OjNbIpen=U| z(35?Kzb?d7-p&e0UAho1p=U#wT!rx`Og*^dHBW}b75{-YcD#MT9pFi*yl(hv82)^`9ZaZ?koI z>A2jt#4QeEWc!y0N{aD={y`^;wUVu8t~-82Q7Bspxw`+MY{E>)UVpx7(9dd5_nC*?b0^L+0~fyb@;)xDvLQH(rLe&I8Z5ML??pwz9lE zEx&o(G_52M!3`h&T4Yt8$#!tdH1{qp58NRqN#s(S%K2ah#BRF^?S#$Bm`e+ss-v{cW9>>jn z7>&F;1#DVl90dEYC!+ccW$yPBAp_%cP9A z9za-{ySG4yxX}~rzMhEc^9-Bheb2ym#wbvEWK}E2D@JJ+~{S_#hD7H&6o|Ic24TsUGI*MM_FoZDv> zQkl=6g^tL$57b9Jj;{YcW7$K!a4|jd8d&eg*(ESbxBEVGSeg5>SY2G|$hD8Ud~~tO z=}ecu)DP`JT;4t#4@L1OBC1a@%5A>#_t{9?7t|7ub?a9>;^{mIFtg9w;4Lh-U_Of7XrQ4DH}0Z zT7CLOG1vGBZnE-aNR4)+NCC-qbR8O<)vp+^6D@=ut3Tmj)FeEBa7y$I#FaIWa9VHb z916&|4msS2zb?e|{f9N^(YfF}0P5o&Cs(q}`3wW3#c?D%GH>WjisQsjdC?+WK$L3 z@&c~Lj9f$+!zkct%*e$=OrwCSF(aFaScWR$Z=y{z1`}jvxeOW*+j&Ihn)`P|k$$$A zX!ig?LW_AxfDYDpgNK_g)#f_P$R+Ee@K-P*>o9MJOqA;|BiHhwtcr3SX5_kOLAIk@ zhZ)&Ux}yfOLwf?`T)9a1#@K~v%qP*NCYviTBRiG>>}X^bo{3iWHQ?;==v-CyKhWP8 z*;}enaAltjUgp3z!5xw`1-HLv8`jXN=!%T{ux1HA6LPSePZng|XE4WMHzJ+O943qM z?lYMG@DcbZ`$1VBfU)5-WMu3W1s6dqyi&sd_be;2Pf&sZ(`G*jz) z#?ty^ohDA9Hr%ouv1s1#(VXuaA6l+*HME+&W2M%|2;=xgnXVp}WxW8eMJiS1o8dbi3Lu{?bgXtE(N4 zo$fY$Gy?adh6cxEBl(DWW#rjzfdH2XJYwmRGvhE4xK!*=;6h8zUZ#w}T9%s?Xppfu zkgaF0Th_RJds~%NGqrttrL1G_q$N=EtZrW7+E)Y~KAO)0jMoj0fz-c<`ajnCx!^&U z|KnErHB;;VSnE%KAoYLNO8?ib_5UZXzlh_;M%^|y#Px4%)iyO#>)$ACbIbx)|7KHK zxY)l{U~T@@rZ#_Q5=I!~F0K9jxc0kRY1d4x{VuKjc~|@HR@xtKrTtM)JI{AEZr5!o z4Ko|>P=p^P?zQnMe0qrf1 zPL1PNDO;Ynsj<9Uvpxdt-<|*goRo*LYbTKz{Ml7v6 zT^UP!FCZ%f`6~4932)2N5bF)<3q^(S37Er2kH7>b;fP*1q9#n^V6u<>LFG6;*8|o( z6;DYg%8;~={larAfy%HXa>t0u(6o=eL)%sO+He}u!p~|F+V#uqC<;L>p8@JP%w;NS z0Za!lnJZ;qA8Y_{Kl`q{dpdIbLdw1vQX|BGZoTjUtQhcxIH3~SricYvat(1Y;R|ub zjlio$1h7nAma-r7y#%xOf;bJs=2xN|`=hAp3tcmiK2~Gj0;@#4wJ zuz~b~iY2hwxXBm@9W&WLRK-A0w^=XiIdf&N=)+M5Sx8Jo1K zUIXHC#3dJEP3G1a^^@^|K_P2;EeyX1Y;8C;rO@vCwsr8zNF7BcGE!%&2@kL#A1Q(A zT}TSoqT=6;7v~6zleyX}j>wH8D#ba%;xquA`w-G%m{-prWlZL3M>!=in<}gKf^{Pd zz5y(ligoOaN7!2a95|1HQ+*J?egJz!L^BVA#>XS7f;0ShU6?~!T4H4ld;bG6wkXW4 z_lWU4n@mT-0U2bjhJ89}wdCi-b#2ICbIKZY1`d*MKyvg-_>||M$!XTy2#E7Rd=?rR zvtP;x)ByRp-N2%+9s%n#nS*^Rb5pZve03psEbun)yaId85XG(@0zOOo2jT0|mV(C8 zmh+P*7FLx<0nt0CQ+XJCh_{Hu(r=WgxPsG~02=?k=6uCbU zmEwQF+Ixege;jESBkd$9{W0DjeFJ*+GoXI~6DC6=D$U4O)dyTstxGCU)$hBceyaKhmvnA>5glFm+?a>bcAY}O!jW@v2C6Y z1}nc=My;EPp~KSH6Tr$#kciKPDz0s1sM~XW+q$x*H((Sqk|kW9g6uvqbbG#MXtIRs z5$M#0YRQCko}tMSu04R4y@2FfX()P-wkFM-0P?BQg`}Fg52>8{GNkZd%|I5XNuvzA zL0VaU01T@Jb^Ja6Mr#R#yl9n}tZq}LUBlbXUM6Re3WXyzG=-d^2QIK*M$}P^R1NPU*$xvG6j8YRL=Y&e$ov_-(+;w<0;8 zHL2;pa;}*zI=6#pqY)d;JoH8D%od%`#dT`QkK#JBMQ5A!=$`ik;9R*S=p?rxB_K}C z<+vXed=>E{>^eIOeh+Z%{v3n1PT1&3k9u8%owETW1*cuPlVBE$+TXan0DU^AU8?$z zFqR>-2PAfmjVRUopjkBlOe7&t9R?5v@R>+e8U3U!+zKk&CR!bp^AS=AB}P?R-}<^j z#QN68k9_h}T?mPOP!SagCMqumiFsGY0I)*G3-6=~ZJMU48^C6TF4oFXK*>H+SE|)C z$*;=Kf{fIJn%5q^qtV{D1r%Mi*CAc`E}(omr7EjA;kZkx>i)RQXOPiVb(d7t^bKD1 zYsr`JTAWyb9=CFFKzBu|M)Lnt7&~*12AEJ`&fdCEtnbTrWC*1YY(G zlH(RcCNk&$b|Q0uOk}do*ZsmqnaB(VR@00z`yf)9NNH>`Ev!YIwdBunUz&oaK!#D^|JqdLOfa5?rIbD~WIgb*9!S0oD%nxv>uN)(TR-~;u7y_dC}_I3)00+gdNkiJ?IX`? zA9MVZG3l{zRshVXWV@uD|K(SKl3rT5d4nH#;LH%QTk0IxWTl*Nwb$Npe zRIC6%8~%I#s^S9h;(5$L9{4xC?Nm52S>_eZ;9m}^(Y&_Ub7Zp2D>}gk+L2najJSkn zvdk+M125Z+l&*7R{jt) zS~URndcZyxsAfCg2381`!p(XVsN^W1%1?ktr&dqH(8U4|5+UwfCDD4X>)sU*+3kwV zIa%b<7Lf|4(sNrCYD6@=*unC z%>!aCP`w$zpW()7$ndvr+yb7s@m~Pw#tkC$yKWpkMT^{avPf$;-sFmK`t>_*tSE7F zA>W+=zuC&o)4u@U7%YMM6jbRz?Kar+@?Z(ntj(U6wd8o>;^n~-s0)FY9YpeYpjJqr zUIV%Wsz&b>6du;---yD)lO<4%OSFeIRtBv6Ff@vXKlFglU7$L>3NQ5GVV)BATMuV} zCmvn}fFAx(gnrk<2VD^#N=z5IvE16jd1%VIegCe9RppiJG@HbQlOWqeF;Mr$UDzZp zyaol*fvP2+CN3^)5*L05ysQezQ;}TH2Cwo_iPdysb@ePT`11KiF;m~I&u?XyJ4@#0 z=Ij?6p+moG+K&W!{h6Vr_eWukR6o3-8j%=g!_c#bz!2%(Q~kW< zF12BhE=2O$TmW|v$OrHOfHGD<5RxMEi6`^3C)4)wRx)+`8n6(Qaz9eZtv&MN%eXY) zVaYEKLuu_ykj6l+c0Pc50%rrb7{J_gNOETNci2_G8dOyl0f}ywWV^g%FL}xS1t2a{ z$0SKtz=Wu4LU}I$Kh_{UY~g#oJm9Nwx%?^2nwDcl~02jnMTwC z;1K>fa%D^Bqa^Nj!RTCzh+PCepR6cY?$XMafX1GrVgrDF5 z0Wq3Kjev!pfV7gPehuIe0>1(nb|q@z9!U0r<~yx0Ep0?5Rzm+5TK%- zTU*IUlDY37MJ-ZvAHkJnP*Me%xj%qf3ThIl4Y{E55t_eRm-`=5F0b7B!7j_40zS)q zqE)%mL1Vegivh6Qs{AN)%be(Q5BSCfRK;jlN(S-wPV&xtzF=Jp{w+{qG}nxT-D5zi zgT1v=0NhDnE`T3cf<{P2AbH^kIA;;4s%#5LH2_5D^d>ji!vv`4p8(=Al4R~Sq(D!n zuycc|TM3yC+o1YSpcaDK1Js5KK$Yiqp?R@}d5O@s0HkK_7lB1apa`pQ_t$&j;^mc!+oFrs$$oC%5+9kNWi8Q!# z0f$CcOal-P?&ek&mdyaC5VDfx&t8^ouL6bEW&m+JFK=ZhEL_N!;kzJ^W}vLi-;RQbzk*amTa$8? zx{^Q!fDZvIh{7WUkg3lFr6C^|Jbaz|C!`+%W!dD61hL{@pzyiIZyuI6p^_>tLgmHH z`5flJ8Q(!3BPB zF1#DI{nmvrr+OIp^xTue$8FGf9ODWaJy*RH0E_XdFk3&KVb-dA4fqnt$bTVU#XkkY z93Yq;jE3zOgS3`~xC+2u2;2zW$Nz%rT$@D%3nn? zs|Em{g!B0Y{w?Io{wVN!fEdkpjDe0fK-xlO9{|`#;4=W`wFvrLNKS%e7;<$dKphQg zJs)V6^#E%$SaqquYC$eP1r)0WuBZhNoQK&FQlVC@Kz|$V^jYVOV9UgS-bDbMsK;Aw z&ZH_9Aqkg7a=ZWz{YyZ}2O#F12mNB+4FqW3eE{Mz^)yYJqg6mdQq^K z)u0^-o7=Oi@@}9>#0><%h&ol6aO*nlR&nSsmnr_fp@pH!e}Q%ElhoXI05L4M5s?(* z1Fslg6JQC`P~tLAuD%(RisMKXZHKGqvH{!+k)6@p8Ew1v4Uh_< zzV-tEjRZaeuphwOiy%1yk`IrA1D$SIVzmR*ZJ_oC^&U_g+JTB^6V*3?NC)!0uFaowW;ScYxFgzLU+F}C6vm-*jacR4uPbxQ%Iz?KA-gazon z!!5vI0xa7c0A-$B{ZF7&Y(T2G>snkc-Y(AHid=Bm^WM?#oCqR8akj{hp z+Tj2mCr}0;`Fc3%J4mKMvKEHb&jD4Hg2+y$Tkz}&MS$zsn$8S5Vf6+r~jKmb3o*i7-5mtsEw zDmwH_D--_?7sBKh zQn8kB05JD+NTx$_l_&SHCzo)e zE7t=+`Ekf~L62OnX6uF8c&Obv^QW|3*rv7;UgtucAOuH<4LN1d)D@%&R9OIEBY~j+ z?gKElBP7xNs-Iv(-9%8o0<~@$fXGeAF&Avfy3hkk0dTRkDhmVh0}%CtAT8==5up0B z0O0oWCX7HvsZj!W5)y>*YcyXEs}{-aWvM)DH!2s&<5DeWOwqTNrShQta_BjO&%)!$ zM;r3oo45^i-gEHjz}pbVb8xkoUmUlbpz{DS{15)l^cE1^3$16(D^&Jil3xQ>Rh)!8 zunI`NuKE&`+2^{5F?A9arD;a`&B#I}bxuKG>^~KSnJr~&K<1+n`gn#};oUmVma_Fk z0)0EKCC3w&Tj$wQzJwWbO5nn~^_?t*~|9&G7h4E?-hJxbkTaI1Ny5)Ej*9GV>MCYPtMrFI1@-iah5ft~dS( zky?tp5AIBgX_0PoT>Z-or`#3!J}y$t>^W&D08b_jryFQ$@)idDvt24ZA`TR&zR4Aw zE3%@zG3GwN z7`|hJa1U00^J7q2 zGaT@rKw|SWCRh)EHj~TDRQWzo`AvhG&n0Jvf!!|2QqXnOHh`3J3xGxd4Fom-*a=|4 z21L-p$>UIF=d@EF*fD-8=0&}&$s>cK1Cqwy20GCM^=%QD-B2$GE50L%3 zV65JXSrFm(7)WRga9xHQI8b{jl!$iHyotzK%!?7A<&6N!Jh^(>Sx+0q8Bru>Utz5E zac!M;hHy>+M;gxgzQb`&c^FhSg`CF5>#q~ zB!t+}7H3u8;xcdanE!5JR_u1Olj5P26$ zbTKx9QNz`U?}NnQ+F0Q41ll=!KvQKNweESKH=-`s&X7eN3S9v)u|k{YK4bA&DK>I8 zP-2>(%7e5BMXktk)BWG3p_lMjh@U+eo&7JNslARohahPRe(_8InU;?R$}LpXl2fWd z?B-uxrR65Y<=&v&G@#r>MJ?gy5=Jlov+yYO%>hFS+nj`yatH^w{I=ntTam6FY;LQf zmh?nlV&waOMxZbq|7kn=Asu*VcT;g$ay#XQ`^#Vs<(9)Yt*%b3RWUqGud+J8Pmk#Za2`tGLOW}sT`Zb)Oh=U8ovK3%SlAg9YUNXqpV%LPqp zsObL(W(LN1KVzKww?d&#mx+vZy77|kJEprHY)R)Ih909EM3$;$+$}$Ji1Lji^Ho;e zNI0xbx9wU}Vya&BgtbtYjb#uC=7WrVvmVl&gMtprn+b2HPdCc+uZxtVF!Hp1zR+{`rV zD#GDLZf2TwGvPGQC#kGk2)FM%6W*Wn~1P6p$PE zx82QMdt|ea>yS#`W2_sgmbDp)!o+rhlyng;%X)6a&HYGzZnW$=wCn6Ve&@BUWHG=# zjZuI>m}nmi$8^}*%bVsz}C~iuOB27Ty)QW{rVH9fu8?MwopNPt;$M!0AF}0O; z2gPT7Uu>u(K4KNAA)b`2Vk6*FqqJP4HWolC&y%Y4q_R}(HfAh?j9$^$6Y)Ou3q ztJrbYPT4Y%Dx|I|fUz?Az3dX9j%7{8%X^cTcB6`QVpm&!pGYOLBwLtv6{dwo`SU`p zW=Y~{-|^CJQnBlp!{pCI>R+tymznk$%RAYChkVv?mX~Q`+gNi`GlaUN#LFkbj$vva zp`Jwz@t7HDN<9iNc2KC?Ji%w3NnbG* z#5zBE1t~+3itWbOV9d<`#b+&MO@7C;ewJ)*AEEx|qzP!xWj_aYLdPI-j{sWd1J1ZL6SDAVlQGoVVuzp6rc4CW1mke#1}n0si2DOMc5c;3=*lM z^aURt#I9ufTs&E*_tUxyX!9QlhLjC%re2;r+d#Kn`OnbHk z-}tOQGwp{=+mUI{?jY37^uF|&AF$L*`U=%Ab;3TgoYAvnj8LaZU+u-%EYPHUeQ_!d z+r>F&h}8Y`*hGM_YuFyoIbW!cQe%9qy4FjZqheRH)|cKXQZ^&xBBuQVV|(cnLY*LS z?lhKK5B9(!Zc6k~RXGq&-{3K7pvQy0=IjVyOcFV+Hi? z>XAbIg)Lfai~={-oGR4U=?n2&CVjEyOrb9KVoLJ405r)bRmJY2ch_DeQe}+Cr2u0Y z%xCRgLd{~^m3T}& zSC_8h?(vc9Z^g9)^G!Y~$>qWu*?sd|wdz*{W5>K7U=Z1Sw400P^GY_Bkgv}5r|0MK z1OPslZ08{fvdn~nb1^SN6 z!8aiyzwV4h5nQztUKBtD(uOs6qkqlmu#Do&Sgo3h3J)(_1V@v9IT^gb#?5J9FN3|| z`cL6Xvj0rBI46Els~(;Qkp(dbQsnUOi9CdnHC%TeOrgk+zaz3{Br37pt9%fr_gh=j zJ{5%3d=iwK8^VR2I2TT%ezH5}>;NG>^qhTx)BSrp#Q zqfaP&MO;{*N&|8ealx1TjI%_Ww?v6H?~&9cnSAW?QZHQf`3!f}VH*?F%`GsH|9%{W zr$7IbBf_kk0ubtk)~MXm!YrPzU>2cflzYB{^>qs1;zptTZ=E4FawMW@;20#dc(j5w z5*4c~9<5-NE~Glg9-oeeay7i`F9P8M{3YJWwaxe4Eb9{3a&5e>jCB5J}RDL|5- ztsL6CBPk3sxY(7&1Wn5tDrnm!XD!f&B7|&g(`n+a`jgY)#36g2+BQ0=Hg^&os?m!AS+#kCY0EU) z22UZlkGoxtsh~>cHtu!>S;|^MvB`7~{Ib$$z;jy*k27q0)oA=`znrVJcz!ugqn=+@ zYt-}08jX5>S*uacFY7ew`DMLEJ-=+wsOOjSHR}200*!ip*{D&^FBfXm^UFmV_55m(D^EXun)Wma;5(!oIu$WccNwTGY!jJYj`j{yYc2+Aj}lEuLTgqEXK; zdo=3#xBA2{$5-N4`{iq`#q-NI8uk40 ztwue+e5X;*FW+m_^UDd1dVcwjMm@j$pi$2+KWfzT%TF5h{PMF#J-_^-(KMAJ?MN9K zPf;n-kPH`3Rw>ewOc#f1+DcQhjY|;-ZKW;wgsD>3!X38XSO-Qs(>}$R415UQQly!7 zU!x0vl*ZAJC@^-yl_qvsPH|2LUg+W>mGUCH^!_fMh`ndos0X;Xqf#!V{6LLcK9!Qh z9E)7Otx|>)FV?t?Oth_oJ&;2#>a?a>uE+0R4k9RhpjcnmvLKbUEQ9o zr@J_89gY0R@6qB~rxpBJ^f@8SWsYzti6D_et$qikaPLXER*JG&tL87?0I zr^|AtQ4QmCS9ZXI@XZQttR*{e}7Z1C(UZZiVy=&`rF29{hnaFzDq49)7&-NRP&M-#X-YiU&+JW_O zqmc$iJHvj&=m{@I9oTNzj~WR8w64dD>rkBrPQBNDc|zmpw_U&NHQtNseo~m2qOnGv zG7eC;ZSOZeU!c_E)NR`bjN7PN;_;wsH~b>;_oj<`<$lY>QSP?1_K?QSbl0}S8V@4= z!mNpRTz=fPBgP-((q8V>1C)y!J zz{L@NN9p4v7f1YEO^rbpNBj*XKjh+G{Izj$FaDBU9Pu}r@+mH!pi=(LvbJ?`ze;(S z`cqvT@rhAX+3j51_UfU%`BuEF>B3a0f1{=hb05oU+eKz6>Lm@+F4RM@`6J7k&%6hj z(gy|L*AB!>H10>ARKvUmYaDYix6X%{Pcycp4;m^=l{%VrKFoXw4CFP%?1YpXbY4~F z0s!sHt0yUYs;djSpQm-xG#)@Xzb0O-aeq9o>1H1!)_I-k=GB>2%`l^2Aa>6%uY}b+ z`T()J*nAK`$^u$*mMO8@602vMJL0;Q2vemtvBc+?ms6K*uQe}4ByCO-AFVUb2B70% zgSN{+tUkcp&v$XO;TcW9FVMJ|>BjPfE+4Th@pF-jXQ=k0##AW#Vi$+c{Vew-8n@w> z4h_IB)wrMbO22=(`OmoRR|r$3Ue2iBV)Cm9#PaK=4g4Rp-Lwyyuh4eguH0Bb?4{H8 zLoSXhjd@9b;kR^sB37ha zj*A;^Kbh#_@z@Di3z1ltD@m9t^xW>LbVEsSa9q7h$T@M;J@F);_JfzjZrm_BpM4fOR*3lri+#K&=ZW zKc~D--9;KVvQ_(2tH)v-b#aUbJ*jb!D<8plL42^r+5eAY>+KhY)ES?>Tz$;je7X1nzPkkpKeXz&i}A3)MF zx{-6e^k9K0Bh2}9n6t)kH}sfc z&dD^y8BLf|gYXZimM{nMFh@+y<#-ZiM;~SntVP&=hWAsLy^)q<-w|e`)*@_jVYZDh zgD$l*&AiXz;T;{GfL(?!`xRIjX@n{3BWEL-imbuah+KlJ8Mzi$E5fe9j@*x{FY*Mg z{>aO?CPcR2u~Hz?jB8Tl1zb}iZ{pfE@*%FNkuy3V&n`T%zT4l$g9JLD5vQg zvbrtuDuT@V$a=U0+cDy5M4E6lBiG}Ke1(3G(Elv-y+U8s8DpLqS%aVR&B!K=ZPD0& zWr1f$xZ~^jcH~Em+1Y|k$0Mc<{zwcz=ldf|5pElt$a(lV--&F2S2qMA*W%~=05;Hq zk-pi7Xm2iTG=1}X;}J&WG(3J-AK7To-s_N|5xE?&8My{mD{_<2@5I%J+%NP;gnnyB z=r$vN#1HI!P-Bm4?C;PHd;f(W*vpNZf&HYh35XKd%RS*??*MJ@Fm3N>ZEv}2Z&#%7 zZM+CR?eHWnhHuks+AAkHMWU#G73qen5y`{VRMt}v@?AC%GMR=?PICH;@^X?>W}ylnF*2hxH^$sToWS}=5K*WJ6w|@U2qLX_9Nay zkx_u#M5f}J9La_8DUr+wqvWj&`Z5)i^~!n&HRQXk9yWA142t2~H5UmY$6@&T$fr@- z&oxR$sW7Cpr24N~4@??jP=Z zjr3slc$D3@pN%Lbdju%H0}PbZ?2ie*&LB_A9vTIFkPc2)9X3Ld;qUnkizg>JMK(gz zi2MR)nJU1cw?i!oU?hwh0?~+^dLQY442;NnG$u15r`|{8)ceSbXb`^0T&VU(MgUHT zoOJ5_e~?S2;mDStJY**#TY^SpOVG%cYUXHhOHgOvIB+}KM!`+!A+80S{Uy3Lqi`q8 zQQ0R5_ahAXTOeWdKZo)oj3Vy-`U2&T)qz~hq$>OVR{;+q+1AhU4gr*Bd4rY39bk=; zTR};*S=vrb=x>epXrAFiZACjzqN)$*Upze)JH|3^qZHgOL&pIc`*%opSxHOe`B^k~ z*>ddBIG$p;_;Owzn;~)a0!UPMVvAhP#G<*HnxmaX(WxZoo{oLqW=K(C6K(A}g(fso z@b(zi<1+W=F$l44OVED07t-PtoXdRH1MR^=?1s)9 z>RjKm3h2F{_ws1HW1t)cC2t`BV@ePDgiOQ)-jDZ*0v*z`J+2*YbCZ$NI}em%P)coXI8_~ zLO#j=4jn>2eDo4Plwm<#qgpQRNwgVG{XfCw0Fo|&w;7mt z_jLgLSFi$UScqb3j-r2h8~OF)&TIeZCku#CDBRMIH9*8CNB#K8(Q=4C?24N(UBo{T z!G-@#@F@ruL2r%-V&&lo2x1v7)L~7rDtHcjhNbHDG9Y$ZgXoFkH-Sw^A74xoqjQFagb{ecdl*RpDKwuWJR zh`e-k4rO%ut;a(udUG#NLR>f(>BNN>1AzSjBxm&&Qi=to+gLmuy6mJE}Dt-hA>dXpsM66-~Y)mQ*)x62Ay?(0re#o8!*+U}h zR-4b-1Ba-By(07O#m12=$VjYKvHll>aUsFf(vdtdonX6CEHX?ygP>E2MTUus2`2XCBE!Tp2}3a!873|x z+^tkjOedJqSD%Tm`*qibe@<_xc#Ve>)@(k>^yZrN6lon zGU8r%&}ZfOvCysv;8C>n(H{W#)lj3pXOdB0frLha?+*g|0gg!=h7r4H?Qo0?=qb|R z#<6l?+@X7pfDq_}%ee7;XP2;=RXUbK<=8JFFhNb^o70a0vH^@GFqW^9#xhqmv8Yfp zSv{J`kkZVuUxq?=@mQqSSxP#|S9S7pF#E$Pxaya2y&Lq)I0s`g|9w0TqoaFR`bqEP zpbZa$<@j^=%yaie+{tg>;0vVxUw!-557O>?wpmQr>OC8jY=%vK`!71hH+Z-;t@mBU67z zrv8ph{hd}*e|r#S1S&zM{`QdnV!krnfg02^>_5t z-_cWlM^F77J@t3=)Zfule@9RK9X<7TrXxN!_#Hj<|I@5t2Ok*U8UQ-4RM{*Fxj9hv$&GWB=#)Zfule@9RK9X<7T^wi(c zQ-4QK{T)5^cl6ZX(Nlj%PyHP|^>_5t-)TMdw>N%6du8fxZ+eOLjzJ&19;c4N?~Y9U zomNwS`?A|1lW5p7^`B`$MyCFbO#L01`a3f9cVz1C$kgAFslOvre@CYNj!gX>nfg02 z^><|I@5t2Ok*U8UQ-4RM{*Fxj9hv$&t)~9=ZEwP!1eyBVyI!F^$6@$-=hGnfg02^><|I@5t2Ok*U8UQ-7z`)Zcz|K5_}j)Zcz-6o#23 zPW|my=scAaLSFW(R{^w>IQ6&xDn=!7>TkbBdN7Goe|tY0QA*MXN*-XKq$aV;v0rD9 zr^!ai_CY#0T_woW-`A5Tr8_e9cQ!)QaP-ta$hl33%R`LfA7&_Z9?(x~@U07!8qL){ z^xN1#ptvi@6aD~1c62O$0O*fEle?imGK$&e3wHrs6Gx{4O*xD>XuGgZ8H1^I3rKA- zOB3WhB4@bBrn^vrl}szVgG86a(H?(Nu(WM0 z=A5+jLr_)PPqnxJXp0S0_t3=jyK%v&!2|4TAfK)>I0D*-Sj;d+Kz|**)FzA(&|gn5 zIgAm|zkpy$7$cy+fneJ(MnL~Uf~jGQfc`}U+l4U#`p+QfgfRm87ZXhEz!A`YCSfSX z2?y`+j;iQw7Z7d|k_65voS?lj zq6B0_3CM^NIB7(A12ReOh_V?`ACM6xAR|gZMwEbzC;=H!0y3fmWJC$bh!T(yB_Jb8 zKt_~+j3@yaQ35ie1Y|@B$cPe<5hWlaN0MVAoLBMP0T zLLua9zxpIVJETVx8s&uah(dZWq(>AsqLk1GN*-XKq=xi}!XQrz4UK|+kPc2)iSCHf zgv3`2J@pWP z7nQXW^I8A!Ye7kJ55E2iaNyH1U2eNlphBf6?lFm<>lb(z-eRA9|c}5MNtDwz{T^rduup>%!7Qp6h}@q z-3d6YY>9GC>5B9K7b-`eYMO>qO`UvFozUkfhf}~(29>pL43NSGBy5-E$f>4n{O}4- zHFX9&L@lAOV1_f0upQb7Gn^vAPNI18!zr&qvzgZj`qd7Ngu9%Pq&uN7>812#FvL?$ol*Z6UDp90 zRk6Ki?(U|sd)e%6!V9h%ELgGkf(`o< z>l1xXefq?L_3`xoeP`~yS@^wwe!tz!Io~&DX3or=JNNEAbLpp0XbbC5MNT;MF8RG! zRxHG~nr56$ecaTcH}(0-_vSeO`qV|awXO9T@>bL5SP8ylGh+agD$KWrM9xG%s z4Bmx4hrbJ6=`g{!nq~~+h*9CkM<6|%{jp1j`Bu}65ft|8 z@RO4ujHGZ_hhL$qM$ro|=`i;L%@|Ghf2G4c&W3Of%gw+Y#-{9!aes%Ddj(3-Rmb2D zwuryk#PMJ6=8q+H>S=uXmZcx|O7EWOw0#;& zf5k0bq_jJUp>&bjLyA9gTIn;~(%<=iO5g94&c~PaB0j#%()sj<-0|Ff2}-Zif{t0l z}UwPP?)z?Mf!M(QbGuxIq~p zdO)h#uZ-C*#ViMHE}wMP8~LO&&Bl>&HU8_}p<0mgAaWtqK<;D5^?^gw@9sIlhfq&ssd0QNuWw&A7m$L5u>Wem8Xkm814?n;c4OJtvw5Mb0%FQjF zuI##UbBoE^b>-$3li|8@bBoFBx^i=i$w*zfxy59(E|&J0vzg4OD>t{8%xr9KZZQqR za&wF6rgi1!7L(z|=H?dDbsC$STTJKHH8;1Ij@LCex0sGW&zoCJ=g7(N8`NKBMZ~B! zu`AHmrKg}WQ-}Qll7%(*j|wn|n#$Kd;f$u7lvKLEDYSMgd^J-u)?w0DM@#W-E*ARX z#;{y0gvrJ5!Qo*2h`Uw6daWV)%snORB;?p%!Ywr_80SLoSNNj&pDC1DttkC!Pi1Gk4R1yzLko zRE+@!#OVaF3u$gW@jJz54mr1nEzG@NLW*6gCw!ivx}IiyUC=pHEQYWp~o|q&h9|0++@?)<&-M)B<8aseTOJtPrZSH zPX*hfYSKY0PrA3hQ3_H6FLdD^hR*y#Pgg-=QT$k_e3g11x-Hh+H&k!HxXr<^4&OHr zz%czX3Q}P|w7%gY_`}5mAdD0tBfOflb3_Q{46hufd}Boj=TuS{CqgXT66aLkc+HU# z&l%naZ8=x7nEY_h@jxaBt%(ZWgyNzbS=xE}3e-=Aa0d{j(pu%}>@GjTx$B{-qqEDB z_#Z#J0A1bnS=iP(9oqm@LF{HkoT%#ZF{s2cxla zVH-fEffqSekT3hJR>T>*#zq$y21f#Um7NFk)QA^C|8zVjVoR zL-9r<=BoHRiy_`*#2gj>l;X`sjG-D7Z!uz2#eb%_*N71;jB)s9-)h8coO>zWX2h_H zXJZn`-e<(xDxOPpzY)>ZaLXP0=#~Z49~6BAdgI&!%jw*ucq?1>U38xD^W9`2k_ev7 zzGsf{^JfEaM3-V7hQZ^%qIcqr7Xtp=6a+uFqWFao;pes#|6xSrzKfsDwDXjU(q{TU5HJts~b{32}EjN6u3T@ppSiuB#H_@D7d~R|)ZWM@O!s z65{esj-0C!;`7dqoTC!r^e&DZQwi~UnIlJ4Lfqcfks~T0e(&bU*(xE9@9xN9l@QPO zaOB!5A+9fXWcVJQs??X#Q{wz8gV6i+Wg_aS`=V#+%P>D%Tv}fy%-%v&(ak*E`sl78 zp$ArIzWb~lmVL0hQvZxKm+663PKj<0tafC#2i7>U+XHJI+3kUKj_mfpdPjD9V1pyO zJ+RS{-5%KF$Zij8c4W5)&Ua+D2QF}Aw+AkCWVZ({a%8s$E_P(M2evq}+XI(4vfBe& z9oh82<+?UpW_n3T4$7}N zGJ4zdf-XQM;#eGaD?(3j*K2yHyiSsj*K4ILisI6Mh{#``E5r=58O!k9Y;nF z+(G$WM@A1kNclZSMh`qq`EQQQ9-#cbBby%hP;aNFp2Qk2`y+$Y^uPytU@f-?J`tCi z9{5y?ULA;TJD|aqwY#oJ@jqjQWsG>h} z0xz_l0T64F{g73i#4m9+mY1`y2XNS88f(pqAv|pDfS|)!oN^wqc0sVhc&&UIDrQKTF6N@8{J zjP)llS+#!a5&~F%MY=R9!c}i=t_vb%Vf@dl>N`wDy2>yqK)Yq35$X0Da>-dQ(w&g9 znjl}K2aUnXfVrqNH^GFJfurz0{yp3f8FYq~!TednSQ$b{S@V%EGPDiUurgs6GTnzX ztem$S|KrDLWg@Bm0(_aeOxg^{SeZ;nS=W*_WjWNavY@m%cI8AGRu=MYz42RF$Rbix ztSo*Rkg-xtNLg)>FS6tbs9|Me8?>)SSgdSnj{kXsM~+aD&1YCSKMcrNxxiRyN55Q% zI2KyjITJNI-&nbF9{$Hivo2SiVdd&ko)uZ?Dr**7bWJ~F<+dJ8(67eIzWZsVKdqQW zVgagd{Brwl&&mN)mkQ*I+_BAAIXtrv11nov^za|F@(C1?N6x6rqsKifj~OeoNPC=* zT%$!VpKPh{nkBLFN)PpMtAUOmIeYt4Zex4dqQ{DN$eqxn$7$VX%0>fOf3$LHgJ zyb;^`$r)BYo$FcoyRkB!UG&)`W97S^sMy$uROLh^{>Kl|idhe$U*ZcIL3GxGSn=`g zs}W~CXsfu7qO%?hsdyDl|134onJV6cd4Cnr?^kiY1|(uuh1#d$yXe?I3|V8%&T?fn z=;vjr>5fzPdA0wqseKh4`R6{U>*+|o{vIVhfNJOKNJ8&MA~C5k2=%pGL7~*d49X20 z8HQy!6e-Y)K$a;i(ojGZ{gJhAq^ALZ?O}RUGpzQbVtcrbBaskij4-xvHJT7_jCABQ zl@ND~a%4=e;*T+oj8>Vl$LiO;vd0OiqGM22WW0VFKx}xH@wkc_Z7JT-p+4d%#EwpcfW5Dv@1Qmvaph=pa$FVU?a#KSUlm+ICK z@^d%>m+AIM7s!+yS+2W4XcC^l!(@f-0ik)Ap)rw_x(Y&3Sh{zWJ_kbU@U`sC)p{O; z@-X9MB5O2%z?-OooEd|h*n*swf}B=@oE3sRsDnHvgFK{yJR*V|(LoN#U_Km{#=d0% zG8@-c!M;eRu~S%(C>y9Cf2NjcnFYGa#YjhEJYv@BZpctu>BuJC1f$^|AmKQX&6;Us z=KdT{;Uk%~iWYLvoUeC6mFthnmJ7#nc#uTPp27e4ms4Qe%A;|H6jk|e^KmbL>$-*6p!{dB2QDi zXowDc9}bWyC@QBRWpT@e=-^k4Uu4ULA8y7C8WrGo2zic$3>z7SNbp2vZLfZ9!r#h`UoIh}EZ28%L6~wasBe3vEusWAtSneIc!ANFAp2h z^@};fXxA@~8r1cRoMimk^~>W1b^Y>$5naDLX++mAPZ`nm%hN`5{qn34UB5hMMAt9R z8`1O2iy3IF@yknul*KIlasBd( zDbn?eIlFj%an3HTUw$`a*Dub=#`TMHvT^-#%8*^Z$oZz`IQr9|Sfk5vq~wx;112E{ zl6GWVmB^7~IWk-$lYZ2%3osz$gcA)2sG@6lfTrmffO=NcY`O3j+>&oaOEe$FPVjbT zv{WCXE3xH5B7?_&8%M_apCPQ#c8-koel`#4_KuA8{uc5(7#a5{6Wnqk+R?#ra^$uJ z(N0G8qYzWq&bkK*H+AhIpo((Kg=m>>0|0e3TQ1y?Cv}~u&qu=4b+TjIt?Lv=MqPVw zC`@%^T&r-)h3GU#uB8$UcnD2*jMDl>8ROq;X&42M<3DGv+iQ+QM2g4?{}uG$DKup*T+xj#ULBoPdbYbZn+SBN>2v> zznCo-hUJT2-q4+qFn)2b=;0S>w|fQew%fgeN4vS@Le#l}$CeAGZq5}uwp>WW*%Kd_ zc3WQEKGa9Ox|xf373G!-(T_D>Vu$f(wp{3*knxvp6(V8kmT4Vxj}?Z@N3$Fm z`e1x=%Y|svk^OET=UB7hSkn)=0;(vtT!_}OCICP`m@O9$u&w@RCu=*~+L~o|mP>Cx zwp>WmrQF5H*m5DkEf=C?M#lQe8BblU(a3Dd>Lwr-6YTTuRzCnJ%WS!jTVKi=X8jl1 z0&ckw9q!nIZEm>`9bsf_xsc$N3(=8APV>qdWj*VaHQFhQTP{S$SP!x+9W`4nOlDa+ zI>+jZL}CVOGtYV!W;Cw?%yBT^DgkKfy+A+}-Od&-v>E|Gz0H;j_3>*ke6-dIAYsPC zdQ&f~$`agiA-chlaSU_Ih3G~jW6K3ImNz>%#C{O^6Gx6fLJGR)L&-JW8JN&*>Yhe>uyEgvL>4P+%=}(Lm zX;+3L+dYzUtU?Y1cc*R%b@Q^mgSF{Ef?-$S^j9kcO?=9+;SmW-zVp3 zY`Kt_&m09t=9UYl9gTdmK{h^XETD=$%(2wOHvs@_n=Kc{HWb_KeHBO~xaC5$gRzAz z7ZPvMc1I)Qd{DqG7owdU8Rr9Txe)E_@Ns9=qFiQV&i~wUA==I1NAWlewp@tzFmjF0 zD||0{b?qsjigL?^Xr=EF)>TK%mJ9E(t~$Eh_c-gyEf=CI9G_xd;+6~1m5z))kTu0B zM-Dh;uXbd=>!-CoK09puv`#=3{gbU;@0$)FHX>@aTo~UN7gM}N7v14wTFEWC=uRK6 z!~JrLE_$VJI)seyTIRpXHyc7Q%qJfc0p(o z=9UZ58-3S9Xd3303(=c=TsJfibIXP3&AxpQioyj%Zt)$2&^pX57ovN8hai-Ox#dFi zR^NjV+J(90Li9G@qYyfU`S@ORpYJIMUBldRA-do9JcRCHZn+S>-S;wt@-Vkth#v4A zg-{jV!(nxYk1ssz73P);(SyEY5c-7wPTHNmPaq5kbIXP3UB1sD3{gQ|hz5Dp733vG zkn8CnSB=4@=)54;WG2NGO^{22;1rE7p2&kdV;Yp_lOQMhAZK7h;ruC=-9gSqhR3-h z$b;HYc*q5LYy>&zqTF&JdbjU5(z#Zw%hV)-7@J^yZ^ghK+R>(F&?~8tyd2%8iJ-M+XZb_7ssnuXE~%RhqoGnUoFlu_{Bxgecdmv9tNY zB)R^G^(LgO>8Mex&q;U=^}DFmT&4aE3hH<9d-xx3kG99Qh?PJs6~A^K#I2?b+>&~4 z5yVT42xF#<%Wm|_xZIR+7Ocj$?Swj4$8NfHl~O}d^*TCsa~J%Vd%>|=o`nHCFpq*UOag%ne={&z@e! z^QV{b;u&SU#9NuBj3cIu3t%<&@_49G#%H@$;>KW8X~*$w{ErX8y}sDzUKyh)eqqEk z6~75pi~ZAxxVg8V;+IB5yWos}b)u2=upawH^cHemgu5`Ye;d*3#jjsw&G<`Y>;y|T zmHeJ8+@?mgVm~|uMm-(N)IHZJbt^deI+mrkB9XX&CDd}3yXnq!77J;Gi+{J`9M(Ph>w_xz7vsKK!BblxWdJP+$selTvHeSjQ&lpJ;htrHV~7#F`49tJecF6`m|LFcqF6 zL>0Y<#ZA?VK|+OB>8ID@!4*^C)%p@7Ooi7t6>uxO){)%`uXkj(!W$gft?))iHWfZ! z@1*IUe7}5shK}xvq;uqTSPAd|`%l*t7Ky{g-F!pUzNjgS@dX z^^dgWkDb)FFUCWKwB?WetfzUlelgdI1)i;6b$@`SUcWil$af%b?04NA06HzrYP4FZ zmuU+-6;FgRQ#Of1xcH(hG-F z-kG-QS)Y5h@*P_}c%n#H@6nbOYia#wJ|6y}Ei2Z_>Vrf^P&*Exv2j+#?R4WrgAUtsmglU!yAx##DvFTP6LVEbCAdneW972XH z5Mwi~1cXfa;W(DG8bQdCRcUON)eJ&VR;97oRuP1dtV&~ZtWpTJ{3acnYjuE7J1hfs zo>c}REQ`w6e5)Knc8+xO0;?BCvLmIy|bNLhG8Y9R>K#*tY zAWx$~KC2t#smi2yq6u=Y4s!kra!v{II1O^3nza^(nWWO#9klQKJP{m>baW$+n8lWl zuFa1vw_ccqmpm1_&R&t~?3Jm`UX|+X)v3;2lj`iX7L7U1UYF|Z_0}*Tj3F+vI z@IdThYXQ6yD~MfY)t(KvmAD?cJk=xHQa!Rg)gxD=dSpkcM|N5?=6K}FRF7O`O$Fk3 z`L{>HK`uCHq|57rFvwym1L!jN3OT#L5PV*Zm>2XeVRu&MVepAc=Qu?J+c_- zXc!)d?Xfn(I}HnBw^(gPOi?cYXq3&h&t7XPT-9heR}r^bOF?S%7Sp#`7lET1fE?Rr z?L;~xA+R}#?yYgeNC>PgA+WZDz}gZ5YfA{MEg`VBguvPo0&7bMtSuq1wuHdi5&~;W z2&^q3u(pK2+KX(It}O1Smecu7mMbB!IbFYFxe@|vuM41RwuHdi5&~;W2&{dJ=p_W! zmJnE5LSStZ0&ANPSo?fjsjRnb69Q|S5LnxUz}hAR);1xqwh4i?O$e;Ls5bIt*emgG zLx#<$l=WG*69Q{-Kee23eNo3yle(DHa;Dx;iaJUNti1`xy|N_))|L=hTS8!M34yiu z0oAsIz}gZ5Ynu>Q+l0W{CIr?tA+WXyfwfHttZhPIZ4&}(_f12c(rgm~YqvM`?QZI8 zLSStt1lHnyYB`&JXMH6EHs}1;Szif(wIu}BmJnFmguq%)WrKgo?cg-lIkKt3gf`$y z2&^q3u(pK2+7be5O9-qjA+WZDz}gZ5YfA{MEg`VBguvPo0&7bMtSuq1wuHdi5&~;C zLFL1?guvPo0&7R0S*I-SrO)_TS8#%g-BbrguvPo z0&7bMtSuq1wuHdi5&~;W2&^q3u(pK2+7be5n-Ey*7>dbxB#Ba*NC<4skv?q^62lPK zoLA^PRTx59Ip!ITLjFLX^BOCaQOMu9a^wMyU?D?bbB^*L3Ky0mQ_dS4D3QW{GW{k8 zd91J-?Yu$y4%~QG0Q^>Ha zJ#&Gy*;tNUo+i&nvh5`}Ph5lA?!l+!z0j*xG@D!YEYkWuXrCZLsb~zX8@Q{$Zvpz) zgO7mYz}*D?0njNAK3W6!5IEcpYYKdf@lR{ua)C<#b@AYT5I#$))>Gg?fX?w?#q|EmwFrq;G~w-S2(?ZkMua#dYo3{7ogYrwS___fmgenmTZ?Q-d7EH z$hh^`WeK9*3ixW5Qp9GdV&Cha41EdijqoVljwLnL`yAV}`1^pV3_dNsB z^@cLqhmZiFd=L0P9z_O^p^V9fEulm^VCjmF83Hmw3}tM)Sq`NG;0li-qr_0gO>rsb z0G{emWTX_|vIy0katcn7_O1qep+_;*70T2OsEbhc06ySROm&4a?U{KFUw9B~e1?w79XJ^=g= zk7By90Jmat7q-SqLVEhYfHOL|jW!)1ltt6#IFtgwtvrh90HG`%;aaH#JjkP%4iHN9 z2A47&@IsGbIzT8(wz-sx0q^uErUQhsbdO6p2>2n7Vmd%5%kFY1M*)A}QI?B$g|hr{ zm+~Xv|9TYD0YX`^$fe|T#)Ta|W-yoz5X#CaE~OLTN{?bXKq#wjn&r4|9N_65#dN@B zbI}1?;;^y`bFf|ucrz*HaK4x5CC8Rx%%kRdH;{cUT4cIsF^=`zts6Et!}dwQFaIyf zrFpX*%5lK|_9&(Yr(-_Jy=)*3M;ZKqE;zm6Bh_#U63XS*x}&K%;IAaAfES-eapv~%EbW?iF-nDZ2{>1s##6<8)`PP9^A)&3&6CJofFJfK zas-sTKr7cLannP;2IynL&z9pfMYzZuj+>L<+z`ds5i>u7!z~Ld-2?^Q6veEJR`hloCl)~VLh5HOy5>qLxUL5~1A>Y*m@ZQ1B@ zvHT^Fe-o7h&E(zp(P{?`bVC3uKF(oSwhHAQxByO}=sVi$EBDwI1K;`}X?vjLAf zjpB5%@D8?JT(t3Px}4y&cg%qe)QeOr9Hgee2;&S76!+GfBEN~tH{<6oR zFU`zVvY&Piw^|9#C&0h}%3T#i1`4S_dvIjZEu zLLiTp<2j8anHx4N44rmV%k?~*hGHdcuIvQ&|5A7=+Qhaa&kR#*a0M0Ac=Rm%5 zQK#Ev-STn}l@&@_Idb4*{LLfA;mt&)b6?wxLbzbCioxmr|MFh{4pWivMu9WkF@c8w8t1`sSQ_{Pf#(BS>A})&1Ai#+Wq_{nU^ZJB z_#=Vu1a#Pg57odQ3;Zgezj-jnnv?qzfxiLtiwAG1fj<>E3$@9?$F!ScQFRoz{9WKe z50b?W{A|3`gGDZL|ARr)jgX%7~Xv>Wy3I_;h{*qa_$$ zYV8HT3wIBUFB5lm;l*)$c>sp}g&P3IS1_HSIxw5k&5q$LA8*G7WLV9bq37c5DFm%D z7SVeGIDbR7;4cpxPOvzLK^O1v`#LkHg2=I~osyGM7d%WYU z4G!8KNLdZKjCnhCLD>gj${G%2ii;LiqM)K@QGeAnYb1DOKcn{K@pbofmEHvI#V%iU z?KB3guAAM-*$VrFbvqb$*RY!7z>IghyV|qm7uHcQ-t}1BHm?V(`*%3cp|pT7egOKb z$7n^5#mmKKwW@H_93Ru>l1W&M#;YE~Fw%w4wsw&s`dSs2!)Ux$GdPB_?gMy`OHsu` zFsa3R-;T^|x}FYXp^FyD4G}}>lYmc!axvhY9wlci%MdI5=ekx70)EV+$XbE}!{H71 z4K5K=?|}1#$D^sD6yD&Gm`sIt3Y_#_?jVt4wK$i3Ikb;kWCOq@9z}{YwHMy7_b^_> zRBv!bdps#Jg*W0a*WP?^F7|j{6T~G>CB^c{+u&HSd=uD@dO5ttq~`d6eK^{h<(yyM z2K#d_hm1edwiTG};}Z%ovUqgs|A15LY`6I-yliJ5jnG}e90cWd zo*4+`bt`8)^;vdlSf!o%U?mY0s9O_Ut=wjN#p?+-XlA>umV4)84h@^RQ9&^A!MX*=f%{4;|#Q zWv4yc?6hayIT7&jB={kD5k-FGSIjFfqOj#f6t=vG!j>0N*zzI@`^5k}WXp>v>~f^j zZSx`uYf3(TCmnbzEHs@_jx$I`(Jy_m(D)GQjAH4k!sWLh-I~tu7jl)7QOb0njC_(c zHx??xrzIs-aZNTjB~5|84sjTC=el6gF=)({Oh(%X7>8j=F9E#Xqe!8}8DSV{w+9p& z(YpZO;8Ik{kQ|`xzX7W6h4yh5apqF)51-NDNjLMmfIoC8s{6ZfpdHr&l@31PAs8+{ z(Gh)c8nOay2KR>}xD{WZy;Qpu^?{C5>*oE?418KrQU>WHNKa__7Is03z5wdLoduo* zXpRSuWbWdxF){;XMHq+D*3Ez~KZCLg112!L1&F6mUA+(Rz5k1{FyK;N2K=r^;o+=` z#mc&)FF3v3yQ;@D;#Mg?>6X*p49+M*ZGOJ;$?V?`H3+0H||pF#@) zTYrX^*lgX$L*Q6eyRCm5R9Q@BO0wq_I!iXcycGIEZho27jY(DcKI)j&o&AH&FVm(& zbv^X*%ixR3;^voGJ*Gob<)k)1Vs4!*0QTv-EjVVNTap|DG#+~EOo?UOb7IyhhN zgZ9oE8GK6(L;*+ft_{EU-*`>{wa_XE-Hi5jL?z~x;^xA;4D!}yl?W@bGcoC&A#RPiS)?p&_?rCLh? zuXZV_cpVFxa5tJG26h73IUBsAFX~!`X*rU!U%k=*nil#-4Fk56+)f$YUaZf9Z9*IX(h4ot^-G|lp7j|ok zbYD_%7=s^1O81AUq4>0kzc4OaBEbQOq>}l1Y^)Vbb5F|5U_wFqu)vtz8pxt_Uh? zEqXlBCKnm2@)NSP>tje4E+MBq+pP+Js6e^{)BZwk?V9MwbVlJcX6?juu#j83COWf5 z;lj=6&qNpMW2US!>f_4d)~<=J<5*TfLbi4-9|HT_+BMOGd{xM6(nL8=O0SYkfktc3s3u@O+XOz@(}iKtluN+_K(Ga+{#tr>hmCsps-(8J~;`(ND7B_Nf{bx?U>9^*6X0AwJ&AHSem?W=U$`>Um62- zXUSPO8^xtb_hQ+>beZH852kfxI@o3IBy5+=WLQ~;(fYLRvuH9St>V{VN_|F?ba+}% zF)8#)CjH9#4TQ9+$3Z!J2v(|JWuyASKbDT^AxV_6lx4IihS!!?1w@L@J}GLM2_ z;aCvUrm^ExufXu#dny?s8SdV-o@Ho(<;^{2jnw9@ye?)FtiuOK_}5 z;G|~w7(Ym*<;%1(hc(~R8yTtW4qo5WxT?Z}bJK1d0ZXj!M4$^!V-zu?D*lv1@|GPq zPL4s;7lFeU;F&R2Jc2&odo`TNF{W<=a>zxCYLBIXOq7te?^X;}IlCVLeAK0=k^vmo zw|@?%{v6uxT*N88J1cod7%*$2(?;Pa$H$aj(v77b?1%z%0klnPko%ELyYp6@Z*&(V zd$~x_VVF_Hhj;+pbs4mj^|?q)aVe_g86J{%KLg+CWzcSP5vNW=*?IT;j0Q=at_6If zOHsvnC^PL)2XvEovYYS3Hg&HI{xL#ONafPCbkC8L=4fgp<4-$VP0hZJw;0rT*= z&fwBEh%tPeUO1Pt*dtHi;1CxV0cqo*CBrz~Ja!De(q}_E)J2>XW>>`Bv0WFmx9vfTByT? zMT?Pcdn3{@)t3WrCz7V0m_qTq*_i34kxV}evVMilTI~lT*>6B)mFiQgY&6D7;hu$1 z%hj_gY}gg)9#s1aPob5y%6Zx@Dm;G`(iP*OZ(X>Od|4y4E4*_F(v|FyPNqh^Sfj3m zfwj=fO1Hc)e+ANg=+dhGEO#=j=rRoM3Vd2pQZ3G32~NMalX%e^lw)gvKV}2yziTy4 zh)^!B0fx>2FrXitb^(-IYk)^#q}IR<$gu~?TRos;A?q}FYc)!L7}_UmkY2NZ4EX}? z(QiZhiHj7m!RBJD*3cfPqW%%ke?3^1G$l{d2g5$Vx6THiOAphkl3^Qw44<(KNGoVd zJ*4zacJ_!57XhhowdVFEf5kD+C8~DMbz$G#29IX?58=D9uHWo348RS@V)w>i$HU2- zVU)EE+WJL2^qUrM!s4?2S(jlBkuI#?TB=!CpOjLn{e^2WH`i~w1L=&yHn3B_9n--= zi|O`EhYRV6`W={#mC@!dr1Xy{;Wt*8lJQLa&W{iY;;Rlmf)q)S#oypCsNdxq95-^z zmH_VIQMf!S;+HCEkJ-3>S#R+4aNy^-992?W2BhmqPPKEPUF;#<`NGor-9E*UEw(T8 z5EZ0*g0!6J--={axItkX)Z{2AvcPZ9^beG(3TNTcra`k~NM;mvK@}P_=MkHwEWXvY zL5mx}?>A`daHSixs)OlVZUr|e`Ohj;<_};Bx|Re~>DvpCq4i00st$Wv6#oHejdg*% zvbQS$n|HaC&1-6HbH#$ID890{phE&^ru+=mUcTG<&w(aua!;xk;d{U@7+}65mTwF6 z1Gz&v1ny8i@Eu#yCtz6(T8;+mV-m3BdyvdffhgF@!9&XF$PZ08lNx#{T4LS6xkLX6 z>agosA(4mui5c6vffLE#;YnrPLz1L!VQNGfO0o8FF2vu^PNqD`1n`cX8W9vh&PT!C;e3r5#Ax1tG(_3l6B&D98 zak|Fes1>YdS1rcBg7JaUV51l)E$*tt{Ag6OTzEsoLQic>j5;|V7DgEhEhoAbjKWwL zRbydniiPoxg)y;y=&Vl2+7q91xJwulxNV4mG4@q_W%crnhGvorGoiA0uWW4Nz8I-R zzNOHtcVQ+}7H_4G?Tk^CS>?MDnmsPe1VV$*QR8w}<6P5C`v$CDgDPBL`CbHO2GRvG zkko(%^Dq=%)xOV&Ozk29k1jPnI}X7=3F?o-aKQyWI&t7z7&M7CdFiA% zWbrt~eS}G`uEYOd^hd}vQObMX%k+z6`V*O^NTy#TQ-ixu{sNRgRm%TOl;=RH)U-nQ z#VYNA*_w^(I*s=U*oN3-JdYtmrIf&>U{9CPQp&+{7sMG=Aah|nlW(7yX{!P>sP_hB zeqQr^(kKsh`oYcw@#^!MUOmd3V*nSRVC2-DkZap|P}l0QP@j@q+=?MN6<-~}S`HI4 z^-$f0^h%YSbt9CwWHsks&Au`s~!DQsruF`x!KXbpQ6Uoy(Vwa9GXT4-ICVInRNZM@yvKMcb}sJ}FO&Nwt6{(VwwS zQ#0^rt=O%F)a)0aeg~AK*&~YZ-8--T|sTpTGbfMmxLS23)Rm~XyE@n-&koC}uSP4DK(=KKeJZavS zL`Tf~9{;TEBa-8ta^7{TwKt`#scu=SdNO!3Q2pd0B-SADt7I6a2cX_Cq-LxKa2)_g zMt#%*t|UIdiFP-z5#q0dNX@o!zMTiB%&v>Xek7Lcg&JoS)f@j8_kdQ-c?!waNGv2< z3-vgto_<~n>POCNgMX+%^$Xxj4c|k8HRKD>(U_VVegVblHC)Oi$~BmqzXxPGbOp{_ zv&Ta1JA}kEChkRtK7|hb0i^j0q3H(A{FO+ILqg5zf-FsukZfi5IoSpy;X#X;Z85WW zs`;BCEdXi$rASFxABjEOSwk6 zXFaZefSFOBh0CAW4?%qsYxOJ=AF@_Af*`IXq(z@|e~Nzo8_;)vX5I%#Slh=`--aAg zqkEB%?#KVrYxE2>r`KpH*H!;mfM1jVnF?LU3jGfC2w0yTn23h6;4eUs3K7zxe<@Wz zKLY00tWZ7@tkA!ZLn`zO60FcguzY%j(x5rLLbF~(?ikcTg<^IeL2BVUP^lU9k#y%E znGd^R2DuYZfye%w>_?!|Y8f9ODT17Zyn6Q^NL9?j37IQ6Cek0ks(>MD{`S0rYfh2x zu=BU)qb7YJu4soms4m`8Hw-fX-&u#AVLgvlG^F)XFk*g?zs9SO>z#XXl;*<=lq2uIw zv*<9ncIQx73WLbJ%bmqAx%$QaZqPpj{ivY_m#D!_m#9Yk*G#e;G+Cs){UGyV{ZB&< z_zs@M$$A(-;T|^JfbUdD6{zHcPF2o=*JSeUol=$OQmUfF`eUH~hN_eceTeR^X1w62 z&|rw@J>H!?2_>c=jJBCzZox0FI;ZNnrl!j5%_^DdxdtP`i>q<+66$C76t^7QpF1mlOc7B6ve1kd;i znA=G9boC!l*cc|&88{r;FcCvy6cTEqUc&Ydu!^85fI{!in-4;Fh$~6htPf!AWHs<@ zf{_8xE*DY(#@>0~+t}w`PhK)zSq**E__lww_Iy2O{uE_3^6?g`Z~HrIH{b#za+ za4M~GsJO$9+y~%st;R+N;IQpyjfIv6s31(>$Q}f^#W>tIEVK9~lua(o1nv~!P`N<2 zf|2J?KF*Nni(3{VMpS<`(daU2!!sB77JdU+U!;GZu)&D#fsU=nshfJA*%8k%-GQBeKAqqP09@yTX ztLH0gnRNgbPC+@9bF#JE;tx*w593~dri-6}rD8CwgVs41?a2=y^VHN40?r4%tT|T7 z38D2X&cYv;k0A1@XRr{ROQBL#{XO(tsi^99Nb$Zwk|&D~u}D~JsQ!%4IyZ60>HuH^ z(Y$NVz&K7v0J|S!@II%Aj?6@W@pG>Lc*OzQ0?>nSu66XEr|JjeA^>_eD!ABb)a9v- z`ocZSspLu!c`aBdM02=V8BJAkJpi8fItwsFbUUH@Cu%Xs=zLixwMt$KC7-jM>=4l- z)jWxDYE9mY1naR=Ksa|_YCZBj=T<)m;%_jWWcOsO!_PjFW2i2dfzgKpBYDcPcHFgg zSE{ut&ss7ACj9JkcEC4Bat#akrb+_Kkuk=O_`Lvh)_;Vd z`?4NREpfS5Vs#S`o1xmtc217XZjNVaa`?7SO=HL5oMMrm+(6brKNHE0P50O&mHZk-Q3Y4wp4TAL7gU z%BPYyK*>g4>lSdbrjg0L0QnoxT_y*+p!xuGJ=pMjkl?R5uhf9a2chHg_ftoQf5~T{ zV+p^B&Kc6I&#M5~wj7+3G3f++_d7j}A)9>10o%CXM=9Xn0kYwf1jMNEyA3}jEZ92f z&{@zwL1*VK5xVKzlaBo>T>D)ePqFY*4#-!8O3j9(fPNfEtTx}~Dd74PFbt42`;UOA z*>i5q9+L!H>CjQL8TCQuIFK=LQ_aW>_2X)c{S1xYi{W|VlvTjl%86Imi*E*WZpc$RSD&Qr} zZA8>y5&mHWTpDZsP-9K>y@8rOhr;yk!^klWb@3+rYRu*5y@UyWV%H7ePWBx=7yq`8 zxlA_$^(|!lif5X+zK2$T$n?DS0B{!vLv3D#B!9!Tz`TKy9FMtW317t;M|HZQIrAon zz6$yoxzKYOH#+zD3-U8v_26;iU4fJ&E4Cu*ihuh3&WaYXgf~;FWS-cTh z)sk&c#gMq3s>`XWo(@&@DvXImNbs)ulVXwYr>0%p{$1$+Z#hNb&hKWZD#87SqXKKI zqx!9ebpR^o-kK||VZG|8s%lu@LdDvR7nO658^!WB7wW51 z^{{#hde(5Oqvx58jq$@t)bDllau2#x&9I^8SrP-@m!7ExGR?I3WOK!4F!=qWl8Q}F&I-$7sHlw5XP6P z9tJ?>qA^HtE*ficIoFoeJAl+UyoW*n$=?<#lY^F1i?x-5hVLI~) z&G&IPoJ)ZPj2NUEE~e0QyT%*28*XDde1+yKxf^b$Q0EHGcXBtpfmHk!29Tega zswz~&JrrU@2B?NNQpo9X&UrYgqkp8sVO#UW@Zii+J zdtSqQ^dEQ`!s9QR!eJ!9c=TAqC#c`1`!oHdNniOELU!(Y3x!Ikz!4C77ilc5DnPU= z@J#E3ccIH-F!eUwViPWEEBHI|PJQ)QOajGx(8FAt?bKaRy48%cMZm`u#ZLVdI?HM) zPj~yi$Lz3E2M0k@#0!{!Zz4EX>H$-xV%f@H^i4OX@$rlym;&Ycz)~Y#$BD)oQ4Wnj zvt6i>TFq0swR{{j0pCw)sz3-^T|%Z>eS~>mUoC{zF5ym>5KtqY#uCQ*?Rsb?zOx?5 zcA5nRe0YUb!NkXC9>3X$<^^Ww;|Jfm+0)g;Qcl}R&G>(_o)CtOnM!J})x_~EV72~J z7(5wYrQ;2;#O}mpp**~0p5VGlPtAt95ofv6)H#^c@>lU*UlF5~fr;>qsdvLl{_f$06F|Zd$&i{P9_6$E*OY?^hgesB^@ z&X|A!O_RK2mIobbzEJF9po!^Up$g>iYPtrN6gc;f0B73W!wrWQ)Ms+8(@Qav6_nio z4j(YMMt8(4K_5trnmB{CGtS8LbJXK$AdKv*^tJfTf05S!MGRpTSEIe(x4_!H5i@b6 zW%`9%dm+dCFpm08TvVHuUZ=NDMd_X2z|UeV{aXDy<*s*6H#cgyd@YiQ!xPA_cI(eU zYF4rYJ+fO5#wcl?Hvq=2(;woHYS#L7IFsdGuX!K8pbL%?kyA{l(q_E**|iMcdVUDs zCpTc;^kFPxDDm$cbfono>g%i58lq39ZO65xb<&S?eoxV4Tux2fJZK8xVdb*|H|Ilh zLl)9aQFmz4zit4{KUyK(k>kzh4|GQf)=zMOuhSOMq?gB`S=I=efxD^62y_O=myuou z!0!(v=T#$PdN0yWqDuZ2g`io#pf3KF9hq#8O8DDjgej|{0?7{Jm<(Xh`zvrHDyvN| zB)RLevR0rV|G@1`7U3)K&LMo`1^0b&A?%DG?N8^gTxtGve=CdtpU&8YhNk;FLCByc zlV1bz$>Ph#;(&(Ze=XP;2pc}Xe>ALEAEd)ZVlEJ$wt|@8g0dT8dg3#vLb4lTXnqi7 zhh#Uz(8WkwA=wQvbPLk{knDySlHCwPvKwMZc0&xwZipe-4KXCUA%_D2%6*UhM0cKYSbqvyCJ6UU(EXa2uH6AeN{kz%WjCF zg-BbW8ynKEA#|%hB)cJoWH-c+?1mVU-4H{v8)8UyLk!7oh#}bxF*F#XIiO@W#Pmmk zD5bXShM0cj8>GYB4Ke){I!}c|C@cL{&T{@RcSB5njg`s>b2r5F*QpPNxf^2oQ65C$ za5*&TZ*ZVQ!vAFYO%C!{xLX0zZ_&ZIDkxh*WVFb_m=DR85TQ+=>d>EnEtSof=w-kn zjEN4{#6-7(t_+_j!B`uV7vpbGDkrlt3QbN{J^5E_f&2>=@Lw)Nqr)|!(X&s>k2?8T zi;QPsCMa>lp~~l>2uU1qNaBb?5=R`8IO34R5rL`jFf?1e^}C~5o6Hw;Ijr0Zgkho)7b4x#h$twRze9ZHFkwvU}Oe2J1CNq%ow zQz40x4rL>4g(ONkBvI0#lqhNYcoXpJ%qT}YYZpzyBp7B~b8QpX9OljY+O0V&`ol}X zsa?u+AWlBX`ex+bk5816s(TGaM{O^z`AGmTyI|}X2zW^+*15IYMv#9pEa~Hb|Lsu@ z2!(OYwQJ&<1F&2RA5%mgEmm*Ar2VIuh5M-R3bI;bDeFWt+I>demokq*`BzOxH0ZC1sFKg4_-5BQ6sAf{ih7 zXMtY_bj*XFVeZJ+m9SeA*Zc$EQ)f^Zk(@1Y%}F3ShI|e1k>X>s zS&xWNB(7N~V*yX|C|iWWxaRDdxaKv0H<9uhzEp&9&Dk|^&DTMBlZWOqt~t9VuK58E zfn!-z^xQOS{-sN_-L zOh26`{*5pyIU-TX%%|6abMa|Bym^?#NmQ~_>n6baT#AY?Dmfxi$ztG1ATPV9sY@QC zk|QQ6`4d22xUkAQ&eA7JRPt}o{^=pPj7pA3RI-?jp!19$q|6OAmUM#j3_MknZPO&lCAE2`Ii9lrRH|VO!;C314}z#LLvt+? znj2U3V1MCb6NJpKmkK@t%b}p zHBi71Y-@272r~l(48gXlDO3jv7=mprp|Czs&}$-uWi23V3lz*@?N`viE+E4otRiw_ zpn##d)&>gu0|ob;3t?k1gnI%749&Hi(A+|X=2{PODnMv%oL*`RmL7ox^;mqOlvLfD zaU;a?LUR`aSnYylhON7MFc=b=%jsqZ&}&?Vs(X^fOK2`Z{(AbT3p&|1jt4_RbH`zn zz6F#Ec&GH&*nBTE_XL2SJ+L7|b1ezY<%-D0$K-0r&|FJGa~ne0tOj6ct|g(lU7+me z0=N{u&@j`Q304VXmhL=wQD51GMp&ac3 zF{yM)&2w0DFEn=^cq>lhs=5r#wIno`_1y;a#?u&LQbib=Yt@A29tP(Lmxnb0eO?oq z`yPsca)<{|O=#|=fOohQmG{grpe8hTAGG(n zh*Kwq=2|tOxi15L!=4p>Wj4d1WA&}2%(59ReB{Y}kKK(n8zdST= zEOJ>UG&hRtoBH^q^nV^hb1f5^+Xhfi53V`x^B9_Inb2I`=9%PiSQ`~#Xs#upxl+3o zfY-ScmB-Lr%Y^3cfc6F#ajv|V z{n|qsF*MgQp}D_%TGg2Aj!dpGcy^X$ZV%NsfOKQ7=o)jW)tGCS#+=+5^YBgg=iB_| zDk9y_tl3wz!_!2_lULdvhRSd2fPpp{@?3nP1Y)vo%$waBaQA_20B?YHs|O#0UDYVq z5pcItMSypE(Ca{A{9D-R}2uW#%69SxDbRYA?b0q{g zjswZ$DUm$kA1=ksnl^2q4u=^6oZGe&(lOPP!=Q*s84paMc-{!WH2{QkKMRr&;N13K zBH2trfOE@E#9@jdz`5O}H^U9PBHe>(f0!Y_x#e6Q6onZAoLe!fE*{$suO#1u0EZa@ zoLkAfolK2-u|{3P3<1uSwP|^nA;7sN1h_fN9SDUTt*xh4eoc0hN#u*zcyaIOgfeiqsz9@2;* zz_}&__?W9TckASq9ltPA83N2IlU$=Zd{BAqQr;i^%9UU()9o9o<1q_xHtj3)WGO){DTt9-o$c#GQ#&$I%u&niXsH zRZa3cFR3!vlSMqa`R+mL5jQszDno`5Cwkv&kpFfXc-CZyI~U;TT`=|T?;u5RtDu;b zc=2H*Rv}?Mg2V+#6f?0MiLpqO>_xWUQ0Jz37@FqkwvvO;4Z^VPAv!!v-~#sp;88xt z0ZLuq2>?94mkKaUw{FcxMP2j-prdiQw#{V2vr8`WhLi6uCtuZR`QCT(z2xLu>g7A` z=<+iti6S&)63S=}J|S<>;5C>bt9wh@-zeRo_OHv~l$Njo#E#SE-UN z4)FA8KrdBN4&Y{#{Eh%a$Q|IQzI0SzO@)dhxfUAIS`XLgCp^E~l|C|k=~pGy;5-CN z9Sq0H=m!!WyL(O3Wq3G85`1!|gztJKb&^XRbUJl`M=iY!)bl{4iJ)qalZtB3(aB)_ zy})o5!3f<3L%cmKBlHt^R7U7uOmKu2JnD?l3M5MT8c>dRGz9S;!%;MYKu`dKK+umS z2&4_C4UNeT*`7z_9wlX|1k_q&b0-L%9p$r(aS6aREg~{>cOIP?~yYYr3GL(o1tjz;rU^;;UGG`c7BW$|p&;Js|{3TW715w7+ce5+~ju612m6F&SNp~V;cuqIR1 zAE3$*Y4$i0oYuNA!HI4T5~YtJi!)ZN?E|C{jW|-a?^@@!qNFQ0^kowmJ>8e2sggPW z$J~2>S5>8L!)xucPsus^Y)(ST2?U6Q5I_i_BT^EI1SO$`VnC%6svt!Wh0yGUSkcKS ziUsR1zK&y?8SGe4tixDQQEW4oQAZuif8WpA`jXo(2F#My>>(Bl!;Z{U!pwr1@@-#?kaVT3KgB$ zzDaeAG!)^Qdh<@K_kWBW+`+_Ya~NEEOh(W);(CVMfl11Es1GQ{lI$yNYF|*vYO0o> zL(yLjL1tWO&!?bBr@!<4+VPH*OuR!+p3i0fErk^{d@J%#UN=W!T-_?;q8?B|v=7vW zeFt^cd{Z@C*S+9|vkK=A;YJe-u+jd&Y0~p>u(BAEd1BTyN1P$+H4;1)Cq@07QPhqW zMX^csR49vG>K3sfhpT&rz~dPAfZ+kt(=*|*p7U53Ys>V&c~MzB}? z;#5zbkfzBPg2#(O{%Iboy~jc+TRoE}2n%s~FT?r0X=^uoddqyh&olJuQhHTU1cKc~ zWpOHbKD4FF;K_=!D&0- zHJqEf3j1`Puu~KUR#hndfxLznwZ{CTnEyl3#u+hi20n%>FSg*|TBSdgydTlsxjwby zFKC|ML+MkL@E$@i`Xr@?3FP1@h)%o-BLfdvM;YaxbgL4K7Mxvu4WT;mFGw{)8lp7M z>Om=|SMBzKaT28mAgxApbvNrIUs^$F&j=)ZI-LbJnv~tNbz?|X<$&82LqJtGFVV9Z z3HHn;(L;yZ@7-fiKdR@gp7eLV^kAlRk0;&lOFzt%KIBP1^QB*AN}uqgSqO@B^nYhc zc}9+2mHE<;X|`-Ns^?ptbd)bmWJ(hlB$#)$FD*1u>zsb7XAy*aEMF@^gynpMrRO7F zmS*8j!Z0H)m3d~*!4qH4eV)#PEp_@qNA-FiLhtSrfHwMDpy>}7(=oI+b7;4lu0%Pi z>Qyua)=JeoNJvHS{5=!k-RmdiC{KHIl8hT!QVr*WiH0$Z<QOZ zx&(6G-%f@E+B_BC^9=Afz$`I5jmh0skF_zys=691_HvcA!N!aog0ZTGhf%|?vzS_( zMNQ5-Cx~fMZB;M)a6OZ)YO8vy0~WWpC)f$Iv4!0D!G&CyzJ`+0}YFd@A&K{-T-UZi%$pL`UU(mi(0DY(aRw_ zc?vjTo6pDNd3>?3BZDR?MsEVo1Qu5D{=&iCFvs&qV|=|>_ZN&b#sSn$44R!M3BIW0{k5Hc!$8i>3-k zPSV+Z+JIAvXKrPglXUj=7_5Sw*9%8Z(%C#o7aV{ZQkFSMXY(XoaNrHXk&|>bPtpZz zeou}$NoSdpbe1_nXY&YMsOuoeZ62Wub>j`)<`KG3zf+m4szS2=awd6%E>wlfR5p*$ zg@#|rB#+RAYHnq+JN|`VgeVKpN*zzPX%F_19lO6 zE{H60B>OsF&ocA{J`FkTTyw8XWMC>I~;v zj2MxbDV0F z)!KOgmUEro!K(u2Uu)5|obT|z&`H2T8;9tDw$1~vQ>5%WVIpfY=ZNv*fHhE;pz!u+ zd~Q3~u#VGAE4L$wLAnHl?VbdmtmAbb5RL9-XMq?jlC7->S+R!bfy|>@b!VobCX;TZ z;iWZ94`D9dsy}6wCYx?mNvcW@XFe-2X1ub7>)9j%Dq02Cq-I#2RD65G6iHe<(H9Rh z>dY_dVHKq;yA!U=8llfewdHiNCg@GmF`b3L{jVAbCh9v;kaBHstw}=IZuwXclZA-5 z{8e-7WFef^lSWKbR=p63)+0zv7b4f~#`V@2nk^;SdQvs6?%!d3V!{nii_oPqgL zbQnd-J`?$(m0_@9Wo-X$m<%EfD>WgPGN=4r_l%w+PGGsku$Qa&1))wS@hQ!cl z!t+5kJTT54rbyw{#!&k(2zH?z&DH^wuS4ihb~HzS3~pNnsI^o){cSsP3|z=FbON*R zBB{Ir{TJvKN$n*?sIr5+ltO(k1UXK$tG)xn@eG)D7ylN5ZklPd%nLvqt7n1G?w?p! z-SvDBmb;do_0Wq!*zV7rL6qy|AR;Qt))Zx9h_WuD3~!WPXWxl3qCIsSX&D!rkdW>Y zMD520%|&PF9A@puj&Fr;X^FAHtTqeb&R;bW{0^ZT`j_(HJ~M4euTaXEIekZg~yV=#?fVn`S>Wn4N08BH0NQKal1uo~Om3+!AS zyYZIw*zH3)PseWhE54H>$4peQU4C!OkCj3D7DEPAazxEY6}wGHT!vT1?i-QOlyST1 zWw*g<><%8zLm7{5U4ftEL*qahj~$P1Q^w=QXjqvto;0Li#?wNk%h(r0MpMQ!6e*hv zYO!a3FlD^A14A?q`=X5Z@41#C7$V&Z8_!e@Vj|Lh0yCGAx_{l(y^%SibT6}Swc*kqH!(Kfnssp3PR~XF;|3mwHNZnT4@V{LMzr*KZ?7fjjr6r ziWTW6Y3sAa&}gTRpkONy2mYfg=njU~G1YE8%PRKhsA~5v2C!I1j}EJLR!7jCJUW20 zFQiL78rO@Gy6AUV(l4~!%}6XrjMrs)I)p_Mitgf)xq=>|sIni2$FXu<3nfIOPT#Wv zxL{s^j!o8QBGGo-loM2JN-7#{M@>Xyoa)gb)$Ry##7_2TTeYnjQK4e>9vvXvOU0&p zG(Fa_Q}uRQt{I_XGmRka@F}_-WX9py;(>8^jwq^ZuA0W?>I9VF@Ou4dBM$4u#O&F+ z3lhfRbG!n>$~e5iqkV@PJ=%A8lSlgwZ}w>8@HSmV%XIiWBS<^ERlksO_yY03IDDZf zBEoPmc9DM6IDC`*?m>Yg4)4-`OF4YASD^3kEgtPVe49u64)6A8-{IRm+Bkfd{@Qo= z9wSIQe5c+BnThZo@xVCzdr?%`V=-Ba-K)=l5+eMJJ`VI2_v}8%QsE&fUZD3Q`SpfS;w=imvspQ=s@r53QQMY1c7G#fxaJ!c6}d( z#$nT}6DeCC>gJTKkG!Vb8+l_#^kuYV$G*|GV>PR79JcJ(x7tF&*!s@g8H-c4{-r-o z+4|nQGv0~3u^;rCw54Mqt0QKs3usHn!d7j{R>YD)0z-*+jagP-2+cJ{MTq$y^2TCT z83eGEw1zCj4=;d#twM_j+S-oC@vT^!qiwad8X+{ciacAxkT=%OS_uK-)y?`hrqsWH zK)jB%K18DJ2(;1emW(&)aP_dBhs>BN7op1j8ChdJt-sKe9UE-Du@t{Zg^EMChFBFy zh^e8L%umwM8fFzhW=vIzP-VY`tg$L93IVRL*5Xf9T}e|qHqKh_n;L)g1x~PLr%X-s zE^r{S#wJ;lA;@VHn`v!ArC!qtvyc(pA(&+`t=t9kLCm(AL0E3*V?oTZZUkYwSCoO6 zYuySW=*~O`#60Ux5Fxh+v#r>Ci$~DHE^9ot!1@D-h})Tx2J0aZS?+_KK`gZX0wU_Z zejA8I))OEc_Z||9t!F^Q-A8T*vBY`-gexkgD6>H9RZPtiM)!PVf}=3Qbjw5Q8ecmQBDG)yh}%U8;$Z2GRj+(N%2M# z}{FB zKG*sN*1TY!XZ-*oM?!kORz6vr;L zS}jJ{pkyL)S!P7GXGWwcGa{E~M&ydjh+JvWm=}?&G9z-erE^jdxh69rJ2E43ZDvHS z%Z$ixG9%J#g<#E#$ZxF}h+K)t^;R*`Xk_V#aEQcQ9}!{ir`V530_p4oA`rX5>Hxpn z7sqy4z3b+vIS_Qn=G^CIOCwYrCUF*Vi`5!R9bRVoR;v^`su;?#+pJzl#{@3uw0je2 zN8p0a>8K0k2wcz+xS(@2I00uD{@aeg1s#D4IszAT1TN?ZT+k7?pd)ZWN8o~vzy%!x z7qtJ3+n{sYGL|cFL1*wqcv5f#F6anc&^bSd=NU)ff{wri9f1ov0vB`yF6anc&{=s5 zmJTe(zy%!x7jz6<&@pg9$G`<00~d4*T+lIaLC3%a9RnA13|!DLa6!j|3)&x`r#sU> zqQ3$cbmktP3(jfzT+P{n%2AHM1s#D4IszAT1TN?ZT+k7?pz|O!1CD_UItDK27`UKg z;DU~U3pxfa=oq-5^Ana)H`$JX3pxfa=oq-5W8i|$NQ^U$QOAP|+Jp-_TdwBQm%s&` zZHwuzzy%$F3pxT9bPQb3-iwyuTyz3-j?s?51^-QbfeShU7jy(J=m=cU5xAfua6w1l zf=&p-Uf2=1pd)ZWCxF7Ej=%+-5>~Dwa6xAT(yk+LK}X<%j=%*SfeShYE@;2e4jFc> zfe$f(3p%@(=7IAy0=?1sxR~)4xS+EFY0KG(77%a*F6anc&=I(xBXB`S;DV081s#D4 zIszAT1TN@|Lu(Ey`)?R{2SDMtEb1~^~E1TGlwYNI7N0vB|) zKvg>iF4$@2jre^?$Vv$pY%OrX)@Ve!6uf@;bf&QERItj(S6$o@ad5h{YAauf<^1YO zoM3Cg2}x_M0`L2k`U3BB1m5Qeyw4GMpCj--$H4pSyJsTr`!7KM z*aekvGN*eyiCWswXeke~=Lo!yM)dC>{)4ZA7c-+t z0`C(Q8>P3x z$5^>RR0!|O6?h-7S(icFgDPj@pDHE1FIV7w?1*|4m?x#AT?y~Y6?h*nTc4JaAh0a3 z!sbzqEG8q8>}BT(yzlp5mk{2UcLIf`$>oh^G_2kf-a%7LFy}e=#?ci4Q63V(1Y;4Jc0Mo zLIniOK z$|Sy}g!knMypQ>G7wGh9p{Gg-@5>W-pSX1r#1niKRZ4hYp1}LWz(Pn?`BLLcIpKYI z2Htl*M3?$vRsKFppDFOZo50~{ zFMs5rA~X%c`|?M#;i?kC`|_*lzFk5@QvMjK1iMrJL!@*u{&nVulzGu|zJd1*0;4h| zDdpkwe1Z2#qn`!|&j3k2Q%6!_>B2JT3A|6bP9t>A_4QOa;eGiA-gh0ixA>AWx~R%| z$~@n|`yPboiI(F2g!knec;Blj5pOh@9MC|-eg~21Ra7AGzOn5P0K)qU`pNKALU><6 zf2Qpc!utvaFdZqGhk7m;$h1>JcwfPBG?pkKysuyo`MD*8_Z1vZep1<6rh*v!8C>X9 zTp;ki11yX1zJg)YS0&R~RweIwc1aZ)enFKfi}1dJ;c}lVA-u0(1n*(-k_+j>Na`d? z2=6Nx#j$oF#3GYibkY5z+OL$*$A&KH(U&8y6i=P0| zDcHB`ED%ec0Z|$3%g&Ts%Cct$`x4%lT){kZgMA6_ORnTLe?zb@;eE+fBvu9c65f|w zO`l}!uyf}?|Tl+m(l{l`;r3hI}GMGzMzc5zL|gZAiOUr@IH2$*fF?f zd?XlU3|!d<5*EVyk^=9eT5qU~ZmE``OL$*W;C<9R6?%MN%rKdu8>U@>_fhvk=-u!i zbqViF3cQa7?uXtZzOL%=$V>_>QCQs8}`gQ+|ICvOPvOA5S?Mv~Ag zX`!on5Z;#*cpv>81nG$_G$dwt;Vqk_!26CM)Ot2_8hkxfN_byV;C*akx)G9#d}-My zjCU#FeMy1$$t`Xd#JBq@s+{n?q=EPS3EX|Y#4DZfzNEnWcp3T-#2@)8s+{n?q=EPS z2(BveqM^zO?@JnZUoN;Ed`a0;P*bIZ_az11M_Lbnc!;l}${%BwH1NI&;Lh+Ro=+24 zc>?bfpH@M9man2p+u&}I6nLLRPqi4t2ssZu$_ejF8h9T!;E(ksrWcnJ-j_7+zF`oJ zYauRU=QWQuNrCtAwxbt7XQ{8JN(t{vK6=bd9GB-sZG+^Zw3P6^q`>=l@6)>=xjiK< zuSc$=f%p9h++dDRH{rmlNKXH1IxEijI$u>7n!nZ#ZPg1>Ps# zl|bCpS5f7J_azOyZwR>6zQlXxBD^mt@II-{nGnzSRa7bAeMy1$NlVxO$=0-#@V=zL z`$XCd$xSJ#yw*Kw;C=Ul`;;%q7}3fJ?@JnZ-y4u0@^w@>;eAO1@B0SaUwug#W30+^ zITjgsUu$&2_V}2P7%?YaNdxce4H55dnGp-nxWM})Vv`}B?yDfe>>UE{laQ>0WL-*H zPIzC^!22!%_llIH|MjyVG4Q@!DXxmrNQiR`-koKdJ4{7?hjf%Px+tewQO;eW3}W;t zXh-a)Ku2uOA|f`k9;0n}O=1Ms<&4IlfMrPBmvP)`J1)iU{sqh(TfPP5+dc9yCoLh& z&90E!WJ!Cf^dj3X*?^9O(``scO8A;YyD!sDiN$n3rV}N6O`_eO>D=zL*#RlN4kd5I zr!y%tv9`@?61i(}y)P+~B1=ER2x7}?5+%U*L;O@qh4<1j{!`_AO`>gHllTVYhkPAX z&etT`<~51mfcs-g(v`1CwBP7bIVJ}0&Bvs{IC_oS3&tUC76Ca3mbF!;aRV*>F z7Ii>Yod#?8rC{X@zYhNcYD5jbIzb+yeA@7O%5dtOb)*-KhX94ZRxf0niq9zj+PCe+ z8{cnasf$=ww}Ko!1L|~ARkN1#%9)^dg4E5+k@dmM>`y~~%yP&#Kz!`izB#el&bmM<9RfW)9&8^yR+0fOh}PYH-81~aU)SUeh)%1=6X&|6iGUb zT*1Iv9686y)JlX%mr9kl>V_xRiE@hFJZPy&8+k$9br~eX`ctzzHPuMAD1B8i?7=aV zRtbey@u~B}p~p|=`mV8d4Kq!lN6c{$e7)m3XisKxs)bb63RO9@Q=5wN8>X?bbb{KK zRO>Q)m8k$Vg5LE8Un=IhliRk)CDqm+Qn}KKdRE(u5w9HegkJF@ar zXR7YbgysoX^HP7yR{kK!>1Qlo>XBc7oE$+Tm?5FLffoa$kX+A+Fxmwoy>rg7&|*@q z2XeWPv5;3%p1zPNypZMKH;{klwa8b`i|O+iX3=bYYaz4gsJV>M;3Im>^*JPs%(eeT zKi70W*LRRb(z#BTTqm)d6EU)X1pTo@zjbusiUmX5>kowd|@c-9eN0esDN>1je5R%q)1M-K~<{@w}ahjUR!{5&9 zv^NWfzYFIrhhy$69R4nx&t$7vRlQZ=0wxo)aQM5hfywMyRee?ALMC%&;qZ6iA|_kU z!r|}2#Y{$K;qZ6i5+<`|^YC}!Ql?=ThrbI~GTnI=4u2PJXEHIHhrbJ(m@b&j!{3FM zGo3$+hrbK2U^+RAhrbJNU^*B4v8r$<(|I$mdKnh(S&j4@{@SlD;c)16rGr6M+qzNs zZ;npSh6ayLA4HAuZ_xs@8*?-|z@yPt(ExC9G?+g!8sO1rt8@%G=4f<)N29IIxM_f6 zeq_{~hYs*Ov^5aJDGwc2Ch^tc5VZGmqTX5P01rS1x*_N)zyr{MenXk$0q8(~+|5*g zr=A1D7t&nD`DX7tvv+d2<&kgi1ae5W@9cJ`q1l9G`z|cocVXGS3(NLhShnxNvV9kp z?YppS--TuSE-c%3VcEV5%l2JZw(r8SeHWJPyRg~53vm0+mX(B%Y~R^~TY(dn?YppS z--TuSE-c%3VcEV5%l2JZw(r8SeHWJPyRg~53!Ck`@U~;nudJ}yz6+b}yRg~53!Ck` zu-U!~o9(->*}e;#?Ypqqz6)Q9`f7}Zz3saIx9{xfix8WTY~R^)|3ZIHL*v;PmhHQ+ zY~O`t`z|cocVXGS3(NLhShnxNvV9je+jn8JeHS*{cVV-A7dG2>VY7V~Hrsb$vwasf z+jn8JeHS*{cVV-A7dG2>VQ>2`!0kJGOB?tYlI=Tt+ZXg#w(r8SeHWJPyRg~53vhV1 zFM1X_5pB!%-9|L_ux#IjW&1AtFdDWMmhHQ+Y~O`t`z|cocVXGS3(NLhShnxNvV9kp z?YppS--TuSE-c%3VcEV5%l2JZw(r8SeHS*{cL8qS*}HzE|FV5&@BWJZe2sR!G5m2c zzQVG77hZw16_)M0ux#IjW&18H+jn8vz6;CtU0Am7!m@oAmhHQ+Y~O{=_FaJ6clJXU zqLi$c5WJ-Q%tG|FD7WwI=NLQ{jiW64`3I21$y`i1?EQ2q66N-t{Q~(;l-qaqi|j;+ zXeBidu%YBcKVteNHuBskmssqV8Q^>slI^=-SDvH|%l2J(3siO3Y~RJM0pYxa(OqA% z3;%BdIWjexKZHziuAu2l?uKB?V^n^T%D46HWR$rqB(tODBPr$EsC+Y(-JjsZ*ATQ) z2@dG?>(t7|fF7DhkKAkw=%M*cw#vqU9$LU;A{zsGsDa7sYz*k3g-qsTV?YlrVzPBM z2K3NkCL`Gx&_hd@%*x?_9$LyY3}ZkKtz^1$HU{+2b|w=!9MD5eOc&&EKo4EcbbdAm z^w1SdC$l-Ahi+gx7yPj*w3F#Pm*ee|K@|TY62ICicN#*eJH8GUUbOL|R-#Nk)@KQ(F#s3gSSWeyTV6KT7W zQgf#W@=g&cLUI0`BFH;Mq?EPn-6?{+Q$#x7E*!a21PP*v40xCvbJGa&rV$yqUpR8p z2ogjSshJE;nC8F0C&GUzEK8W$A+$?jqc&^@gm*{CvI{{($&u{kzMf_1p+1ePA{-~H zYXhtWc{j@Hh8CuRyc=cpLxrgz??zeuuV<2QoUE!nO!CH*HJptuNH|Vb&8tXe*-fw< z6W?y~%g`!Fd`z_6-Qak4CucR%alyyLPC3^?0}_0UEBF}K+5~)zEBF{!@G-97V_d<< zxPp&y1s~%IKE@S%j4SvUcMER4VfR5;h`54}aRnda3O>d?1$@U9e2gpj7+3HyuHa)_ z!N<6Qk8uSb;|e~;6?}{<_!w94F|OcaT*1e<1|Jh7J|?!AcZ62Ofq=osl%YE&h>r;z zr;$s4XbaxPT;-vK;j@N@hG$x3T2@Dp=)@`CRAH)mw>^?{0c#W_?W;%eIH_=62!*@CJA9Dh>r2zLO^uqv8jTfvVtR3JI}rh896oNQ8wmj3N~zKE|m`fDJ2x zk7+_0R%*_|carC1opHtr)Qy$#vmr88CKxNk$2b$G(2C^#{^88z zErs})HpIs`vxNjcCP{pZGgnC95t78mIP(mdDsleqREY~HQbFQloQ7tWXgh+B*~1cT z=dah|TS`30KoW1#hWHrg4IzP#N$%~8yl)8!zy@?7ecO<(YD0XC^Nu0oAV(?ZT|+sz zsg@z@Aw$MglK2?sJwsyDGvWE54LmU6IZTlX5+CDy=z`tWb__ly8bZC=PLBQx+;$95 zYpHnp+m84cC(qEt$F!HqE71F(+g@rfDMHnn_!y^9KMX;x;~0F*JeW=pALDe>OrvF9 z0ODA^2!u`$ALDe_r-QH(#K$;2^ePZ`;^)pF%Jn)B5#_KoIcy9L>(XI(9eUlG_!y_B z&PQ6t+Uuy#p&9@dD=zq$o*4cLtoZRsd`nA=4>mOlIMS+-7zl?L5^yBqW8y=F1U@E7 zd`!I3kXcw2F9kVVNO&Rfj*l>T(R7H9iH|hO=$jJ$_zAbd9|?baG({>%d`!HWZo)so z$6R6jyWnj4M|@2DLa_pTOp^GR_{F9Sv`6A&;+Gf_#!MNPo`8&|jLS?J#K*+94+1-1 z#|0nrFP5R>Hyy%v8{%W)yZqjmBt9m7iy?!m4e>GY+l0hrcxCLq0~t*jx0_x@d`$d~ z>%m4Df{&Sw#(^>(8;NgI#^Wu^c(P>~PajprJ{K8H8PAw9h>wXsYk`e21RtZaq>T6f z2wsx-nD_^&GKi0fA2wu2C2wSXd}PRgN)jIvKVnE+7aaZc9U5t5rG6%S;A4`+$Hf0` z$W$$Uat1vkC?x&`OEyk^Ni7v5J|_Ove6ZWOg!tslqzKVGh8!ZkQs+(iwDNxIijdq z6CV?ws|%q7hYddF^q81ETlYf3IDC#*ARtEK@CJ|e9d7h!-{DOj?K`~Lqm9Gc^og`g zhtD&Dw8LBVUsDcWARZWpFBC;YxDgItr1?A8aM<8uiXCxymwrFx@XcO54+oOGlZ}({9@LifeBP|Z!V+3i3@6_i*W+J>tJTMObUKH_D*URDXy?Q;A;IP5R zTx=YERcbV_h>Xy-uL4#dNjJ6X^IE*amZ)NddVw`_?Y<1x;q5u zKn5Rk5Cod_2l_8abm;piG!C0)jcLDU>qC7@%GO6-Qzkwpenjt}Ejw=TF`eSDWyinO zF(izw@64UCIA!Z!`m2YEyW^aW0^7N<;2^e&M2 znD`{?R0wk0#0@@XXDiG?h>wZSvY1v0;$z~oty@4?3F2eobF4c+*a_}5#phbT0})IR z9}}Nv-3KC+AU-BO-+B;4I6-_&e1Y|65RnA&G4TfLaS&Mv;$z|qt$iS(3F2eoi>&=1 zoCNVP@x|85AmRz)W8zD!zk+aOh7@0Fy#=CGLK^Hc>pc*O1o1KP)2)v{WamjWFSkAe zk((esCceV@5=0&*@+y9Y6-0$4F*ypOG|n*`P68a>r5)ZzF}cD&-l|NBHyVdywZrkx z;h5sEpE_))PJ1e|nMo?l>Y#m@YH8(si*j2N9}{0`-OgYa#SK1&&(oS9VR%Wo* zX9oN1%wV6B8SD-6-Y75F8#9C5Xnl`jykKw24EE;CU~kC`_SVc`Z_5n!xz^8g+64PN z%fgyfj)e4ls{m<)R3az;IJh_$Vlo$Ix1rdNNEqqX#K*)hu<~Iqw>WO_F+nV5n221K z8IkRo5oyYd$mN+4xgs+nS6VdYMdYf?h+J(&A@L$|O=d)PWJcuL%!pi<8Ij*)Mx@zl zMW;c;x|}b5S`-UxWUIPf#4Y8 zW8ybkQH1Ik;$z~sSVd4ehWMEHtyVd7R7c=r;$>!0yTdyDJOqt}L*-vcT@j0=sJ#*n?bPcaJ-h<;nuP zJNQaGDY&x0?#cqYD+}zdEU>$>!0zq}!ev($*j-s*cV&UyH4E&nSzvd~0=sJ#*j=;0 z?wSR5*DSERW`W%`3+%30V0X;|yK5HMU9-UMdJF79F0i}Pzo5Ue!0yf+nG23Au)DIr z?#cqYD+}!IRp{ISR~Fb^Szvc%f!&n_cGoPhyJmsiH4E&nSzvd~0=sJ#*j=;0?wSR5 z*DSERW`W%`3+%30V0X;|yX!5m2f4uRZn=R^U$VgNZd*lvWr5w51$I{!*j=;09^?YM zd(k-PlxSBL*zG)UWP#n41$I{!*j-s*cV&Uyl?8TJ7T8@`V0UGK-IWD)R~Fb^Szvc% zf!&n_c2^eIU0GmvWr5w51$I{!*j=;09^?YMyNkbY9hU`mclR3l^EDd4M)%`lwgXvU zcUK^7xw63S$^yG93+%2eu)DIr?#cqYD+}zdEU>$>!0yTdyK5HMgIr*DA8LhCI>`dN z`^-O(F69Ed`y7L(O5-TYeO~UjrCeZl_tU9JDHqt?7sz)?xxnte$WD|ftwbjG02@k9 z=|@bz#73T5$^~}!Wd=B3#btrLRae4TTv=duw?I|9W`Vsk@iBy>lo213C-|5XDd!6n zhT_wO!mdQUbR}PPON__|r(1Sg`N~-?U#*Mzbu3{rc>`(AMvFhklO*mGIE&&L37TCFsT~uYv(p zO3;l}!PQ;6bPaT@UQ7qesZV8n2XgPhrwb|7lb{<*KsR;Jdm4h5ePLHwJ}8qPp6`=` z{9HxWpF;d?N~H=mR2e}xmVj<(1k+Fq?f94?DhRr<4Ctl|+}^&VD_6`_89_IefNmu7 zi4c$XRn)Nr-B<#;;dN*tWQ6A$y>R0MP*D#IW?F{Sb_%28!vML;*A!r!@Dno`*>Dg@mG1$4t}*4rSyh$^q) zpDH8hCMcjA_HMlk%-d7aV}BYAseo>H+4@f@2?EOkd)o)ViZYoc$v&6s{J}es%ffa< zDe*G-Lzq;34uDwF=)3Ru1@bqkmcjZ$g&*VQ<1%KRaJwI}>Ptu$}x9Xx=p1 z{Lzf3)t|x>@#(?@%WjA7U>MhuU(MtI1KY_zk!T6yMh%k&wv#`OZWIT~skIhteI4@b z#HR}>HIT5Ke1Yx!7nl#G1U(7c$rsoTEgXR0^^|ZRVLSN(+xY~{FVX_ScJc+bV`0i2 z!N-(SLD){df$i|wpkrF{3|dFNf$j7McW_Elc48GI0^5olGO(RN;EwVoUFo8#;OWtjf$f|O(cG5e;|SXc8Q9LMlt`8zl|utr z_6E4sFHz9rY*gKoP#FYRNx={h_`ponD2!mAv)Zr3U+B$}-p=-fo>zgZ<&HG+ufkeHcld zM5)34u&mrtgZ&{tX?z$>evt~kbTTqj4@S9ttj2UCME&U?RsuB}kTnNvw|@T97OS zbtHCcL9!G~Ch>so`y4|xg;Ch21u;`FmEr$b_Z`MSpUiS27Jdv8WfV*gpp+61vGg0H zT|q3lf>?3|vE&-WQqUll)A8a zAeQQp_7O|urw~gdihab=X&_RFrMVy~eZ&&Wp6Mf&m?wo;S_mSASR#=^ERksR5lhQJ zq!3FqkU}g`veQQ_kw_tyR)R<&mKt$o4+IAr#1cnAAePD*C2pYUYmYG~nJ%PM&zov- z>4I2dWC@FT6dw_qn@i8;anKON5(nOckiO$m@t{WsQ5extZu|&1~P(Sn%5lfW(7xezz zLKm+Lm;_6LSfanLLHc0}4Kb<8(ugIQcm52WKqudwvNU3eZA`a?q_Z#Wx|Q)ROCy%# z?miUak-mzm$UrPj19y%u@k&o4mUtO@J;a-Q6;+XeSh@<_-=rn?O~J((#M1A;eaM$| z%9I5K9xlo#jh1 zMzo3y#L{ZW*ZVrEA_K8>8MxQ^lCF%gs>nbr-2>5sM~O2KOZy=@m=c?ar4dUKu`eP1 z&R0=oX~dF*#6>61#m9uCA_KA11>EwK<$FlB~6OgSea?QkOG zaBAdm?&2_r4!diXJqzkt_7wTgtV8m)VJ0w552@IS?{RwQYy6(C?}ZsbXxQ`R$|||o z5ZDXuv-ngImcfLIa(!g@lUtDKG`ZxzgF9j*kq!1N$*D&1US#(R=wBcz@9O1d;)J;i z&!D6VhDKjJT(me;j;NOW0|LfClsDy39OmtH0X-5K&&aegV$2!y@O$Cw1H8;J%ana~ zfRQma&hc!FV(YSB3+OG#dTq<>YnA<1$&6CiMD6_neFs$b{x`K3eKp=a?7!LiC8!+9 zR2!`rzrWe^MV&~%QUHJ@jR&jIJUR%1M+eo3ge3(4OCl1+NS+bNXu^^pkip}mc`&9Q z(wrkSV5-7^>*h0&W$Yr5Z9vul+VhBPm>zlz)O;*ai26T4)h>t9x$}VA!CO0qL3uoD zbvu}JK{sCmLlan~p&$AG1~s03UI{ts6!JfUn%D;atcfoE=c@6%)Vm9s@n%mTE`6W0+eMXq2Cc7X;)0BC|8yy z(@rsZd;f)SQY;S#=R|xaFpD0qD!F21O#`tQpH%)SYgJGluhe8}Pevnu3uW43<6LmA z!e;`r>G2b0@oR#rPdXXT~~@(37Um z^#%7p;CVBZYh8m89dl(fVQ86O1{04`HOhsqsa({mOle*S;f_qr_o+FR58of90`)s6 z?8E02y3B+ge`-fudT63_^$9Av4f?082FvdJ3I2bMtQW(MZvFwkmxoZzb@fO{ zeb3}A+dh3Q=&fjkx;du@#N}R8I3@(1;CO~O%#tx+g_JaP_KRphXCYTLB=(9q$W_ne zoI~IbLYBD~BGCwi?Npep)I7GxvFLvh_+#JGgdFqP7NdpAdMjSG2?v+<%9XjMoZEQ85kGGn_K*S=^em3Xha7}VHbppE;4H(FYn;a<#O zQ?Qq@wDe1`QO~qQ`))tlgcct3qP>LC&IKdFXxmysy_cab0<%S^;VGx8c9WdGM zls)m-hL7|Owt`pa8|BdC7-wf`j;Pj?zNgW&r&Qw^L_4b2!$v*R;%OUbOS_;(0_*2& z7vd=y;;Cyq?E%eNGLQC@(;d9avO6xq^y0@*!f=E)1?GH5LVEeE_yk~#j&6rDBIn2XIQSA2wFNzZ8cKdAz)qOeQjtm!GG%U zB{q~7K6(st9I)m>r5Lnso`Jm2XL@!M3alTGf|hZ;zsG3$J) zVL6O(-{B6Jk@ks>vBu;5In7(q2p;9DP_R0K55D#hYb%)FizgpJb#U*D7^$ZaqdT^W z8jI}@y1oIP)htx@r{c*Hu$Ik7-|*<0K+{hneT>orH1L_lb};&BNS7|ez5a8_eT~qw zpl|5ML9c8?0f*7I$IMmsSEAPNJ$&S@%*9~i0s>7lL#n~vsMMLLty{ocz#Cz(X+{V^ zZb(2-kL9#SL>pavFZ!ZtNP_+8JhT3Z8-XHJ`J)Df^HJqyJvdL~A4tBC+xyEN4S!PBAz?fFot@ zgAKlB*v2b0#{LK*2L{DV!84v2CRWi*O1_#V#6>@cT^Xpe8dEN+Gx(%npB(58UIO){ zo7bS|!F@B@V-J{JBy-P`W$rl^w29ZrIFOGt==vn~<7#APIbDKyDVQ~AaWiCgc|WLz zfhd9z`4k19YVD@ES6b=5>b0&-rWJI81JVkXAJq!J%xDFCha794J*zesIk}_`i>3is zXR=Dx^y!Kr8Y9_Y$l(Aka4KxSfzN!-jX#BFD=Xmq72wRN1*h;?H1K*P^u#%H@zo2o z)WAqssD`G!0X5JJA^~$^WE@mdoYge4ng&)gyF}mDwl@XpZbnY8fvAOi47AVDFobC# zo%;rEwCQMSHOmc(p<@7b$K-W z<#LvNXJ9$5hY^9cSN^%z%5!kl(1g=09nU=)&Bh2?f(4zX*(fTgv zc>XsKzt21UpM=Nv;8KEFQSGgea1Rb$9yGdV2sh`Fy)nvHqcF9Q%a`_jfqhUs3>wp6 z7&``?9! znfu#l5XLCx3ica(E|AB8L0)D)n6p4;KFiBoCOl;RBAuBx0h6;4TD*ee(>ZHz^{jc8 zRKxoS12>~*dP-=5wf94bJ&j7M5bSd%v2N}?1a`GF$P1x7=J<@d$$tS2@_~H+x$BSe z+%;LAyWU5x1CZE%d=t6qnUrof99g8>9frb}RG95Ocjcf0rQ1D|g)*eqO@?x98}M87 zx&{jz4tE`)huV|*leG%ZMGgdz?p@<3e@>;L0X#O1$YA=4sb7`mV8I~-O=DWRX)J>xyGW5JN?kQ<@G=kg zGmlJXPB)G7p~c2OTeMm>{-(LA;Zn%ibk=y5$=m5!zQMO#owghdY)!j$2NYQ=4~gOg zE7FLF2b#uWw!8--*2@c?-3aVH;;DaX)B{lkyPp0Np8l^!KM?&!tA>}sWPD18c=4%8 zJCeS{x1hyK93@)+{Sx1YoR@gA$kCDEiaOU=zRb5gK5g0S@Ol6z+USL5o?VTL8tmnI z($6*Heu^*nJZ&S;4VL+D9JGeMgmRMoZzP>`qExD!xH1&O)O2YveNNB zA0ozksEEc}hO9PkERMlvAlt1YGP*;~i|7sm*&XBu znl6`SJqAqke07Di>(@w+W%syJ=x;&SEb^(I2Ozz5B&1j27mt*>1oQ@Z#=P3VK$c05 zxkgMsLggE1YKI8lA}!A**NW+%NXxzcI?><#l6Rxa!8Oc;pZ0I`%I*06GrHYbb7n2U zBte@yLfu)j=3wFX9*>;1_U{-8Q{;?wPr$?zpt$Z?(Azw^X_{Jh0Q6NpJwr9T z4w|99-Qz{}sfI(~u?;>WJiiUf0L_85;Umb|2H*DbkoOPpI6L~v<6%Tt_Z@h;()a?M zb=LXV_7xiMik`vojJF{NT%JEVP9)xq*v4C0B4@y5lSJD&grrqL> zbT1{&sfK#b$WNY;CWLvBXQWe=*KHokG;)_`L^W*o^v3#n4`=G_N$KtI^v?D5{*zNo8V-Az2AfQNMSD4Z^m2^% zb70sbKA27{6W-BINbNm4+qs~>YR^!ZH!6tRSh%2Wz%Vk!AJ(nTheh21`hZmC7K5mc}wgmit_Vh z4I^QkJYaN?+3;q9M}w<7=0OdkFv0~#j|CdCocq`rZg z86iDzn;8LrkPOGZjCzy7_(vH5FC{IDT|bHZEz&ZA{wyQtkECUU{YCWMS3t`M`m4|# zLCd4U>+pLoM^J68{1V?^pMX((A>4~wXsfC}^lEB->O@dxcy%o^yn5rQPtI6ZcOj0+ zVc2I4aQv(X&4Xh?qhrqm&2jG&kH>MZ0lXhPnxoMg(5*&Ev@^!NMsPXq^%6;H+(R|c zHpjP%p}`h9N;J?-Fg9Nep3MKfTxR~C9-EsX=h)2O(DLl8+YR0oLQe>tsVX~Fmii^^ zfrKOI-A0O1<+`S+h6f>9~x95p&*A-c8lRj zHCPv!P%Rgk8BvNn-d3N7F{3khEa9gAv4sARvV_M?3E?ITq$Q1J%#dORdnW&yHd$Ne zWs)(&jL^m@GiGdtI2SRqM_UQ>qPmMgn=!-n!Z`?R31=`PoGoU|xzOZLP%D~dC@A)F zuk~|>Tjajd9}95J&}1{Z*vrjkG!tI%;PFj{=f!_MeZ}=ZkjbrG3oc7%(?Ija7;#=_ zT+cCqy$}ort(y-cLnTJW)Kl*w^sJ>kHvlz0RbB1(&&QA_f@fR1#5~F$0-a!Zx&(T{ zK;6fnB|NonAeC9{89ZuYkF&TAG$X)L>ycr4O-8AIL@D*fu+H&lf^>L3;7qjOy()ec zJ);`J^T+rrE$b}$hI#7xiImT0U=YXk#VzGa5zKHhHAL%5IzhGLyH48_(nEzg+SP^>&-J_3zKYRpC! zF6|ryV>cP=t!2m}51H3OyS5Ugws^>_y9cUtyOwz}pC4E5g@MG0h{5qQU}=ZNgA-QM z*oMz9G1vDDEQ|NoW_oYGZM^S`c@zrcp4?}mX!hlTtJImQql_M7Rl^`?`~;0(MFS(} zSXEmM9-qFcvkLXGm}~Brqs&9Rpy#Y|xK!5++VqazaGM*d!@>5lG*p7e8dxkmOvO&g z^zid^ldpy%!75utae}TC3pU!lXW?$&!kkPC5wC`@ow)>x5pz^DOhEsq~hOnU?pa1OE^d+3sUC>4yA< zm$|R-(2)N_t<_$RPQykdC2YwoA!9Vb_E;x$p&UK)G7Q7$TDo~P3>VgB42@4>lvpay zt2wf({43~sRp^g|xiX8=Q)SJ0Hq0a;vUBx8*r{jQ>=wM{4NP;PQ9%t1OtR*DDHsuy zY$tUX#mc}m2->w*L(pPis@(vNzf5OtCp`6Kx79l#7%1NNfr+Oxy|00(`s$Ro?TxpS z#oL>Zjd)1Ay*?Lt>X{aA&-1;#85(Ody?qJ{@wTJ>gYWHi^!5b^T6+5sIKHh7Gym$vn$7cN!KDQ#Lvy|2W#< zS*_&ju(6vqE&(+WRPFcBJQ`|2ICVoA4H7T(o8$RuA5i zjiQ@DkBvefIlaRV@5tR*;z+?>M(Lfv3$Rkpw8ZgwWRu&G1C2w}K&{J>g3e$_9N!B_ zjlT=c+Hx>k#1In(9<{X(2L?ifzJrkEjmMc&d{VxCOB$#?&ahI?wD@|d?`s1z z8Zv!t1VeoN+W2}SeLWw{qkZLBWBa?nl@Rq6UzehUUo(BZkG@_Fx%euL;d^NeAEbQ! zA?+&_&!;Cp1YV}EOpCAo_I=#}jh&gk-V28K`jhe1JqTYP0`n+e&$z53>?(U7L|2Nh zg%g#!6Q5KYI0jjlasvZujc5bYKyUo7EkbYT!bu8RCCbL{E!vjNCG9JrQNztdLq0}w zwXy?}{SYY}^e|N9Z+K#Sa~q5WC2JSZwf&p?{X2iVc@11s3pX*YZEdFE4%+LJ@YAWw z@O1{V*MARZ&RVJLb~a^!rjIw69lZ8fuH(EiS2`B0Byk(D+uLQ6kc;Uvd4?;{ba;a_ zR%#5S1{&*Pjt%@9PeuoOF0#m=a5YOLQwD_tbf0Seps8F&{qDmX6S~MTGP3YnNBx~3>4{&e;9|z5I z9YbQ=&r69Vf*Kpg zb)Yv&V=*)uhiNOFZPQjF_2=VyO_g_%Dt`=F*51wb)KyFb1AFlM?Q5sA#dQ-6EXt5` z8+DHLbasHlX4GBi?_s0nET8K8Ca5(ynIf|DL5-OURYS5RmW$wZ2v+WfH^)8C<$iOVDA6<%<+^XcW=-M103j;&8oTidG)IZksj#?WN=BT9!=#B5 z)DWl3K$|!jIu)lisW=^iXB)ns1IugeDi*Urmch@GkSG(M^B+bKDrgkxNYE0ZO+wZuiu{0FDEjLmXWR^RCn<#IB2j*mdGTy!sJgch zgX7TrYCpcxkDA|!&*Vj@$vn$E8tsUGA$)Z6#fa2R_{`@SX8Rqq?>CSLO}xUMbcL-J z67zyz{-*w5(SHQG!>49Mw-k9yH0>ax>t)?2b!u1~r3T`%)*j|y6B4yxfHqAe!J6$@yv;I8oumzqLvw<9CtLq8m{AL>}42!R=RJxQ77e-{9LZCujI~0{kpzcj=jOa6Ko68 zd&)e{VQ|jEvv(Jd{+Jr$7>BMNXD2ut&-Ef&Rkz6M`ZwcA${|B#9O~Nb)Xw z7k!oR;Vi_}^wo(X_!9(dnv*2c-$|h{P8Mp!AyA8#D|?ENzX4e{^ct^yCU*Gk)AZ-s zUr>Jp?sAxn%#lY^2f=u@BSK@G!9Z@HfHU-Q@jI4K1#B6=tX3aJ4Nt4Oc;ED+$}nT zQ~N$t{kz2~WHHnJU%-vffED_M26(i11l2>=9yI}|r7Dj^@uE}9mDr>w7RCNP0sVn6 zq?>!WUZ{I~b~l04))IAAyN2 z(=+Po8JIFlU_q%S^*+2Bi1N+4by%3kfN9pXvxKe!E$i50VR$B;jf7$Na%THGMh;->Pv+3_I`17kkGwBto+z5t^;=<%SC3ybwkO9d=|hE%`- zXgolT*~r4>tZvt#L6T7$8iFiR1KXfoTM0pn8W8o~;C@N<%Fq&DeHYcMk5;b@f#V+= zABkGyQDR*1LP8_$iJ@r_KOzCR9)>PBB_jZj!k`&JCx$q}e@|NG8HTPr3|c0o6GI$A z>p<5>+WP^jlK^3_d)ez8f+kCh8lWRFszi1{9W4!4J`w zVC*1cacCTJNQlmbIn)1sf;0)jJ|(olmtF^Ht^J#$0$A4!)p598A_&Cd*{6qcp)(d& zsGD~o@AA_!f^ZKnY7dGv=L}cKMSTcn&1y_{&yb5M{ScLp-5x`&zR#H=3kI<5UA*?;EiiVr$2kZNhuU+5-iO?E z?cq8vrmhnb(~)Qxi3HDIuQ)Z;OB*JF$LaC54BiazIF4PL!TSh2b^^lV$9Z@3VAFWq zb-n&x_bD`3UPGwaJYT(=%AVTZD1wMH)&v6iKUsldgtKC7hXlS2m8yo`$iO*p)&F9K z+G=FrY~+8%I%W%m+1W3KSmh%FtmX?*(A2pZ)g1T;)x57gs-ti#bYGI{sQ$~gbXw*$ zhQF*GbzT;o`N+8Jaq1cRUeMK2jju>0E$fYSBl}g+{h7M0sB7q)BWOmLBfKWkN>FS? zhN|H-1Ii&EGEb;@@#YOYKz#0k^97mcPuU2{gSH_qikUTH1Z#(a@K|GiTY10TFTEDToMh22)pjmuKqB_C)G5a4te+ zUlQJrk|Y%7uFC*27VjN(9SqdBNAY+F9A z;=WGt7G1^nW%2kie%KK2S1Fv&bStF!#w?~2Nb{9hOlKp_cV;o2gEU{7#dK?=`PM9^ zBS`bLSxjeb)y;)ib6-k=1>ij^g)2#P-lFBrSxhIkYV+zW5(QiJPnd-jUQQw(TJrKN z5=jsv`SvUlxs>qrStRl{Yra1#=bmjK!nfnn=b#zLPt9zo!u7gUuzTw1;6*3m-!|QM z8(MEC{uD_ta0oZjb9Gm6iYob}#|e@_?4PIG3^flOY*k&WVYll=(CGRFQtEu2hpA`o zdcym<@<;RJclj>R5X{X6B)22mtQa!Z&ex|WaOhX5lnZ z(L}6UbIzu|4dSZRN(`>vyJo)HX5KYZaSWvRJJN`0%71!~nDw`-Qufo5L|NGw!_7vRo-wpNw%l$w6-C#rEqyKKOD=hf?fB3t> z{y~4ecY{4nfBzre4R$?r{C9&*3PAt==XZm>0Dt^PE2(*a4aI*q7#q3&ZZHNo{cf-sDC~cF zH`pfFi0F{K^!6<3$V+d-=B2lR?HGeX-DiRC)YeZ@I(+P7NXPk;DB+&}UXOYBEuinj z$E85EdSy8z72m9Zp_qFB*H{W+p2|0`9;0Rf?v0UoykNHgx5mhPCR-KY&KOz1WTF5! z#z+H`*#)>SMiw%eQ-IrIWD%3C3#$67$YLfV1-L0jmN1!>COeX zBSy9}nMm@67-?dT)}j*fOo^l4NT{PKUPI{GM!hr47)Enz({$4 zn1BZ`TRn|B@CN>`FEj)H+G7wu{5`S-!!X|vX0@#V88G(%>l>J`iiQhE-X&@EX#-9v zXM6$kE=lY9C^(&Y(+YU+lH}1jYrtA^%p1bwhsUjfC=(p>T1mbk%&I{}sDOFHWFQhg z9?$IF8z!MP3Y5jydj-0dLe2UPz682q9;qzzvPs+;mBrg%p#O9xgSbBjs+KZo?kyXc zT!(@JHP}EwLGm`VAm4@t`{%o8k=Pvvp(8sYXl=aCexM`S_=k6mksjsKlD`Ib`G9Rt zg$3)4FuZMds^qtvC0>5scO`$=ejFw7 z%}%jZBSG@_A3%oCSNN`=;IJlWI($`7u#zH#1!jU(v<;)&+QF;e3Ba}I&xH7zFK}(P?x13?liXp*_9}LWe*^q5iEP`em{H-AiRV;_(^@dEUSP{t^3|XLJok{LAWWI{Mx)S7# zhRjp3cS+u4$XvKVa+e`ntJt?BZ#HC(iYd(dgSQwmTg74|Z#85>#j?@7g0~s6m5Sw4 zy4#Sb>i>(m_l}aHh}ws%d!}cmcV~8IXJ>X67}$kPgaww2B*{60h+;r;RH6jQ!33g! zlA{;_5d%sT5R{;RAR-1tF`=Sh4j8`YsjBV;zV|)n`{#GQALs0BJ@wqab?e?+)iqs9 z7u>SpH@am6>o>~!2G#R1>xs*gy$86pSux$qagg;i||_o z;pe`D-zf+`4<)>yApHE$U4Y*!2tO|({6RtZc{Slh1>xss2rnrJKfgfuqk{1BcEX<& zgrD~j{;VMU{5Ih)3MxPUejD9#Ash97$ogVG|5lZwLi+hHI#2oeGNpvs5uUaF&VfXV z*Q#vHK=3i#MXJ}TV!V!l9+sZ2YN)odL|D4INaHdhEPY)~Brr}0&_HWA~08D6@iD1+vq77fkzZm9D#X8No2H&zyj$~6@i6P zP((_@O^`#T(86-6A3|f%u@th`>zZLmDFj4-p^M z7!g=Z{FcUuz*^$BHAVzB5FgPP5!ga}RAWS7H}Nrz5rIR*?`Vt&OdSe*Tw_GwLE;k{ zBLa^RzpF7Ku!i`g#)!ZM;`cO01YRLNr7K_=7lqte?Unb7O4!nPeHd^52Qd+b?ZS=!u*6v=a{HQw^j~^j{2#xTdVlOzT|JIRId@S zX8MUxuMx3k`ipR_G~B?N$-EEnaRuRnBtpGL#F~l!@71T*h*&d~B-Cp}teMIY>NO(P zOw9=O8WH|$N2u3`STl7ad{#AtHB&Fb^$KFm)R%CBf><*RB~b$ zHz|lUQ$<3#ob(!4GgT+ttk@Kh{0Rf~f`TED{59c=3I;{;ObWlOAin*~A>5)Mf?Sa? ze?>uj0jWXws)C3)@@RXBR5-i?UAjZo2jGX7h-3W;kug^9NSkXR>lcq1pI1|RuT)})u*3&d@TWg7f8soP0 z6mdvnOsX4*Q#8h;x|ujtW8Aj35QjC!ZEHJmn#P!PcN0f6#-w|WT}sy&x2>;m1&To`#9Q=eE_~%RhNXL`xq`w-hVXXww35cqB$txDJfmBxzK!}S%Mi<3fv<`b z6cG>GuWGb}5Hez{Q59NmOP6-sZSc$}l@a5VUVJ}Q88KdCCnF|k>}145jh&2emZDBZ zI7?9{Bb=qElM&8R)X4~EDe7c|vlMkQ!dZ$s8R0BNos4jnqE1FQOHn5yoTaFf5zbQ7 z$p~jD>STno6m>GfS&BLt;Vea+jBu8oPDVVW{o`cBJdK@}14G8ao;Bv&K$F{Gzdw5x;8eWW;Y8I~nnZ z#!g23sj-t0e`)Mw#AS_DM*M5ELnKs2{HGW}G^VV>cuIF~%XiR7O}P zL##5wCj~_$!a2}y4uMd5!q>qZhz$7;QgXTI>u9o!|5I8DQk_gMo+=tqxg6?j+5q0D zT$yw+Qvd={9*F7dYNi7uMNMk%W@Z8e<=WBL-7F0dmTO1f4Q4rjs9ZbxdYAT(>Hs5GYLfJO_@-X_*P?Kc%>)(Rkaxv(4 z7lUf;>vh&GZR z&jIYOpxfdAzQRbgIFOVu%hB#Z``Mz`FAt-~Us_?c;eUUx)8c8a40yPEh=!M z(I@Z8$F(0zh_w)`1A9in6cOTK^!`s23<0(f{<8{UVZy`c{hum`wI~mx_kX5flH;Dw zo5BKRtb7V5OtU=1zO0Sv6t7<$M$fl)rh5GmqXY_ZI!Lb#U~im<(fjpUARIu}a^dWc z8`v&U8SGa#ei5ZQ@3^B$sM)$^Ob%ck}`>Ps_P?ith`4(pRJtY-66sY$E zZoD6&N_rqrUnR&>s0=iqBt%;F1?rWw9Bs5A?-{n6FZPHE{+ zE$zQlT5jhHEe0qpy*p9MP4|MnLu%pIDfx9H(3g9_$`<)pT$mGaU7&v@RKu2$$FaKD zsI-iFj9T~_jlgKB1rOA*39o}}0mK`=I)uWwC%Q=ee`bTN`FbbVh zl$MVMQp-{H=;Ld&eA3C)a#m@{pe>&^L$&P<{PQ*tr?ez*;NK8_C*R6O{!_Wm$3BEY z&)v8;&L%cA#=UV1){g;GW852iQoBcE+#65PD6hu2H+I_zY-x<1$ea)OjmKb*oV5c1 zNs7o(YO;+7K%{sBWsT-&`2;LX^#;lr+fWGKNLzBWt}GGn+~IZ+$kiCO=2JtS#;}!d zK?vk)3|o_Fn_i(Bu(buTUZEPW^)Q30SEz<-YbE1)G_Gtdl*&Y;B`v9JR0jcDTNtCz z(wzxuYfIw>6vCq^(Mq=sze>Ng))=-*zqQdAw%$qG+iDD3r61dA3|pli+iOhUaqb9o zGxi+`)phh*UGErEU0uhuu1oCU31gJfg~yrb;lE1PS>sDr*QeL& zI%mA)>iS&kI!Nz)VZ5evT{33Eo6GRGsOaO5#&i_oojY|EfuCGm;g$5?&l+QWId35F zFB)6;X4$j52>hn8N5pSz4*a{urU(yWy#CM_>l@{>zl=BZ?@ zCjso}6AVoW^89Uwbegkc`YHvb05l`GOfS<@&hL`}IO4U{u|0JY?bG>~H^1JsW4xb;A; z83w2meTnVlnK6L6BE~y>jQ8*uZ^3dMz|P5afLFw}qa5RHHO9MQj5oCy?@6)#20nOS ziE+w~aW0H;(uuuDg-q!fb1}vwigBAi#uUhay9473{FNxjdy`%NEbNhs zUAuvEZ<71-c0&d6G;en$Tz0*LCZ5P`%mZv9p$8AyxQ4TvDq%ciOM`B^nG(iRwOi4Q z-CVJFs>0vV3gS^1k6*G|D~Ly7uMoCT&?~KN|2wU{zar{8%6cq-)e6II zR}GYWx@C7}pX3eR?m{VH{zFY&^H6OY_M%-t%h`RyUOWrGL(SWC74{Nm=qHz=v|M2D z&l8f93jmiX7FKm&kCsbldPJyMhvvdwA)yCN$wiaBvIs)Tf>or1xtlsy=ki*^K5!f! zEuAARIOxM~Wx*ke%0G~h793X4vEVHQ9Sh!;(6!)*gdW#|qc6G^93v&ncNxWZo}vX_ z`;R-}!!580De&h&{8lOOmvS~9=<-iAY`LxL#jPy4Exu&fe=8Obbh!gy|Dzxt=+@i| z_^*O^pnC^}^-2eKsejq9v(hPnS*QiP?W}b0{Hj^AB7E)9cab=8HDNm|oebjYFj@04 z;u^wsRyw##&8-0ae$C@s_XfsGEq1&H?lKi~fNjm=F4L|&aFWKj%XB7A));r08;FA% z<1WMhN?|)sHf`SD?Xd9(dq#L!G9V>}9Re*LmLE4?O`4J+B9uG&B>6L@Br-A!XG z6E@@nch~Y*7Hnq+ZqPiI1^mzWb`Q;C8BmG*jT*zDRcKL9g*~{f_hfrFD;&W7(=QBY zFNHY(RX=Yvj=FujO_Cy#U`w|fdqJRYFB{LGrQxs+ecNJmM?v-N6{XAV+g63S7bp9+ zO=G8T+qJyYw;h^y`nFT^PTzKE?DXw5h26gGQP}O^iKp}jFanSpE>{|*G)!E0xax6xy_wfwanjm)e@vt1rA=dkN z25hfNzvrljG_-Xid9`)t4Pc0)<$SXwTmGFbm)DPTqE3YJ%zIIjew7*nGv`}V@x$S65pyZrkdM`Z_^l4O@HFs zHO5pkjJUVPm}+)$WZj`Lrkc^@`)G`v-~HtKYK(|~OZ)mMjO+~mO59&#l>r0I2IzFW zW7ihK9;6sP0PNVchp-20jGjzm&xdG?@OQ^3gr{>hIi_spzWx2g?`Vwd;T_dJuCR%0IZJ#(VFTI1p=!UY zF|uU_qkB?gWD8H&vQKG@?8qX1Ut?s)G?-?e))?7wFYyN&!>6}U--j9_JNgiRq%pE% z5b?(vBReYc`ZF3MJ52WHtj6$NfcR65u{=*9{!C*${*4l!)7UFL^`*(vzrq8l`D?|P zu>2nO{Jh4n^gHt3D9p#d{}O+vF*K=c_`*DedX){|%MhrD{U8NJ`|qIn2Hh*)>e z0nCV-5pP872G1xI@EE!!#-qnsRm8h@ZH4iuaT(k(J9fu-)VMUhaCF7e;3kdnAn%5j z-7x+%#;w0O@huu-JoC6T`&Nw+u{7e_G)BJ<)56;|M#T8vitXMShjDH*mmYU$j4!Ai zxb*0waSAb(9(^?q5o77mPvfBM=|ImM_Ot_T(SsEMhdRT_b3Y7H4jd{yq8vC(3W~@f z-a>|Z?tu^-xXAMg!t`Thsdll42XiS0F3}C*NsM&hQjHx4F4Nd?;Bt)}2d>oEao{SA z9S5$~*m2+*jU5NB)!1?1;~F~-T&J<)z$Y|z9QdThjsu_4SUK=n&)e)N9k@Xe#SVPN za|q5=4t!2}L^*Ji6cmxI%2G z;CG%7x-1>|y&{So_^pRWuPFy!lpawIyd(uhq#XyukDh-J0XVRv_b*JDxz(ftOL^Zb z!c;N@jo1mVJA~Ub?xj7dC=A=V^>dd?kC3uQ4X^?!3N0V<$l6HFg42L1QOC6*YDO zR7qn@mH)8)LX9!0f54kcWsNbZCumOv_inyl6YErM`{g06t%Gu&N#UR4*W*s^UyS~Qmq+Q$F4%wh0-cW{6MZA#|6p_Da z-}T-`5JJSKdTRlnQxTu$y%B}5{5Cg3>5XD(fa!d;ccjbQrl)*k+bZIH8sm@q))DX5m`gy@e$!hOo``pDg(ctt#o+4#FqVJ^HHM_} z@*CdEaHh(aL(+xH!KMHZj6Y#>}wP41y8;0_9DOF`~B-do;#~-b?J&7$chN3)|8dBYGll@_vmG;i<#{ zjS=Bl#J0wW@B_q28Y99j7_p$nh)_G?kj98m7vdC+5uqE2Q#JO=o=2>;?0H}2LR2w) z0MNNpdtqm2jF!66@=T3!rSf>1H5}nl9xrLph05clq@ajA%o!(P^@b2U-rxEX_~lx% z-2s-3LO31wJA0tki<^{uqB2NfJz|GiHC)MIim^&*$>9p?5j?`W)s-Bn7+*;(IZ9zY zqQ_d}AgNlrTQS8WdWdxvJy9e2E@`G3(PN|`s^{ZnQ>wQUqyiE7n!TN9oxsKD?c>&4 z$d*;LWpCG6zqyt@q1xl_E}yzQsi5xcGgcO^P;PlvG3+b_*DI*|`kd9;72Kp4_LYLq zE2z8rqICxZCGnCXihKIBbp&Rqo^F&Ts-C_etx!GPA{$aYeMKq|ks}-juUdO>G3Ktb z){W?SxGs8X+Mil`>i`U=#AlW}ca0`Kr!g{n0`cb>BeSOxf1xq*Z8q_j8e{I7L;RJ- zn7if^f2}d*uEoUXHOAbvgZG|qG{(r-OZ=_I7#RnMztb2ag9n1!7c|D)HIF0hdyO%7 z@vw0F2aPdzeL{RuW6WJ&5MR<*&0RlP-_aBQaAf_g7(VKFowM988oP7XkJhV*k{U_B zN*5}R|0V@Rtt?~_vN4vZq9Zp_~hKgx$9TXc9j(7-1Q4J zR94u)+;yCM6^$`>eMnqYW6WKj6BlWWx$6RPHH|TMRi(#kXpFh51p8G}V?;QMxR%C< za2|1OjS=C~oLlQ^j0l}2zD{FA=quuS8Y4pA6W7<+D|_C^cPo27f|?sE26I>VQO2&R z#%SqQ&U(!?#+53s8~Q3BW0l8SN*5}Rw~~S)vYc94`w|d>$LISzn5jn8lkG0>y}@={ zFy;%jUaSx0)7eKA*28(R@1iTYL@^l7N^+^fdOWZ2m4I@kbERT1o|WV(h4p}5>#IRY z+1lfZDIU>_e9O_G8qv$8nQBC@k%p+AKOvh^y?s(D5D|;>@Ke5dxEQ@X>Z^&~-&SAt z_L%P_*Rpq1dur~&BjV!<>)xL9opB}KQ;eFtAbCn*-P;d*ekfPH{ZKJ#_JZU`3hUl} z;wuYDOkZHmDyF!%@A@7i{*>*52Ng`-`fy-UeTsh zkmk1mf>FLo-H!NE0K(DlI9}5I=>XB_9BPaDGXXN?hMpbsmj*~g&j-O|_{#y5kvnyE z++P5YCI1tGo#`(G$d=o7b_stqfLyt4XP5NX1}HDL?d($i`T&LU|2NnPe`A26s9X(~ z_VY-tno+s4QO4gEpsw8Av$Oo20P02MCP%ivJ3xby@_t;_e-l9ClDxT;^WTYb^JsJK zmF4(H19XqdeT!WGcz}MOM*U(tfbw>z~G_k=QKjx5@go*b9ce>+uWrzNFAj zg+7CJ*!wMh!QP)0`dgtkK5)K7LfKnO+1p6j+g#b(LED>$E0Siu*9i8?_gf^*UQc`F z`z;dLA=;adPa{!?Pg9tC(jY&FXOopSlIHO>fb|+fM!w%7u`xi&9r!d8hw+J%=JDxG zoX4k?_#L0VgwJLM#PAtNGQi8PE*BQX+XGqI*D ztqS2HZ(?>9t;)}!RlVT`f1)a)9!N|<2<^lr-~-r0p#l zW5zm;t1^=gA23=jX(_?^cyqy^T8ektb@9y z4w?4>YD7NY)Dfx?fkZcGGHwRl-xZOK=Ht(&MX2U#h){_!8T3p?L=<#JyhF9V18Xcs z?c)xUmkE6$e*iols=eE}csuAlj)*A#UMAQ&Q^2wx#z~jKD;!QYfg@U@#!RVR6K>7o zc@8PHq}df%pHhd_MyMI4J^bVl;cZT2>Pn^nwbdOa?+dV+zE09DL3MHIdb~RS8{m}s zg{^d72Lq0|M&up{rVOos+RxCGF&Bl!|C7i_%Mp1Vh3&4$c-oOKwM?bmQp*Vx&bT5E zN|Cy7K+1zRpgH#0_!abJinNfHRzT9E%oze1jte6ll_l__*z$j)2Pt!Zg@Ip?t?V*z zEE}xoZH%gH7Jaf4BKIK@T`aUf z4UIvxbjhOYaBXV0VfefWmA4lY_1I?jj%aKYD#yD-K@d}8>W$0cd}A(Z7Zfvx&_rs_ zk7(OdsNLu?`E4PcdeeXSl)1hi%t?op$*D55pfoB|Z+-y=8=Q*%aAoMtJn7Q>#q3V6 zPtg{Ks1ZhU+4zxOkRo}~zxhAllGIx&;*-}Ibs^L2Dmjt=37flhqGMJs(04c@B7Z6y zy6t&XNCgv6-~nUB4T*x*bkgk+)EZ0hvC5%E!8x|xTd*fDqIRpxl>eF6^l1S`s(ssG zRQH7c0D8uV>MZklPoSb~VL8-ryvXXswi@%+ z>&c-hoOQ4#s;`q*X7TmL5gA@AJ6NtSuazE*G+;Sc9p{on8nPG`=2j?)H0nf^fk>0z zyW#;lRnp;+rc$L8Z^oimn14VZ()@9VRP8(wt_VcBY(Z7lSvJ-E5*#72-ff5SOw}q`JA}uIL1b zhyH{%PQ0zbc61~}?k{Y9-f>ir?2q3g98zCC;}%Ff62~X!mHWUxNZ-h#kK^+cDnBkJc+^_nqbrmh47n-) ztE``Tmo4w2WFLdv`u|n-AfzJ8o8Bx08`}%H1CFf7-Ps%DilJ~0$xlFh;gUrU!z57hyn&Lvat>tzzfnaCE`cfRq%2TFwZ@S z`;C!>+KLX7w-stc{tFyHo901?*k}s6wId=5UWeV0=U<2Kj9XAU&|$PqT^PL0zoJ9Z zrm3K3J0c>#B-)I;P#a;A9$5)yT`{|k-h8P5GIYAJ1I%8RE$G2(w*=9=@g8bFa+&=3 z=yYV;tvb1kpTYcD%-+gbZ2M~%9MZ*U@M#=B+813p-R%4TzA`GIwzk8lQC!e~^sc)x z+KslLZoZ1nyD0s|HBw}E9)iK!jxh={;~hDXf0D-SE!$gn>Jc!DirIWl|NCa372dIp zO<-Pj*@ByKRpgC3(HG+&YTtDjLE>>Sy=c2*L+w(EBWi*F^ z9_fgP{6U-mkMTe}nF$YodAOL}Pq)0oqwXa8G??dHwt$Pv$cY)KF!ti(xWimAqZLeM z_P>jLYhio|{yRrT6x5_&PJRLB89eeV2@XrgzdVnJ$@&$^K54Itlq)Vm%&T`p;pP0fQ?T6vU64b78nQE(` zFY@svc4m`XD`HgQ=Nf}|XSu?^9{>LX>Z|Eb0#cT!-s~|JBC05umEE zXu>z3CY>VRv`LXj@6ShKDNUPH6X^q3Ol^ucpr#LGG29eyKusUSVp`KCHAVVh79&mZ z2GsN+ET%Wb8&K1SvKVNJH=w2uW6^HLH=w2uXBmp|2GsP?Eax}H8&K09VKLl{Z$M3- z&vLvO-+-FFfaQ#)d;@CwLY6a|@(rlzt67eszP(6a!*WbMeK6oExiH5oz?-C?I_TDQwlv@NAd02A=CV9+glImuDJsfvsbzWoK6fZTVB|kgaj-0DEVdC#^Dwg1Q@)6BFR~ARj@}AoZyePupbf9N4}_;r z9)Qnl4Zd@XFbh%ko*aNrzj_m@U%e&OuijxA;5$tHSG=UvN-UtPAz#w!S8rzZoBnTL zqW_9_uv&GuDV2>gL8v#bq5-}N)%H?@?fp>cS%Ms~y&%`_^*qjt>kll80T+L(?q*+`ywc}FM@LW zA}F^nf^z#JD7P1I%EUj)_mMNn;D1l9IM zP;FlX)%HbDZC?b{_C-)_Uj(n*zVP>YnD)x;3xB^aXs_J92+Hk?pxnL)&V`5>l-n1< zRVa&~+`b6P?Tet?z6h%Ai=f)R2&(OipxV9&s_l!Q+P(;??Tet=z6h%Ai=f)R2&(Oi zpxV9&s_l#5mD?Bonb*U{WVwCepB+Vp2j%ufP;OrY<@QDJitP*koQseT8GgBa@dV}N z_C-)`Uj*g$MNn>E1m*TcP;OrYe@Dvsf^z#JD7PE1m*Tc@QUpV|Mut6qDO9D_z%rPiz(c` z@V`apiIfo9^1uB%iry4%U-*yEs6Yz0FZ@SYA57u)h5r}_Q8=YBYW(joQ6ec{v3#6K z9!+VOjq(XPI76gHpTK2y<%4J^{LtGNz57l=RG8ttBLVhvF7cXa!}{Ne|C>V)FwND& z!BpoJkv?~!SYyt3oWufCzQj-ZAE?LPGSu4jZOk{upQ!a(V2EO$fz@;aNoRt}ap_dZ zXu6@K>ws$N(mXmr)7MM72dFz-I%ixoJjtA()EA_OLGFjlOx-w5+BhyOCGy~tw zmEoLxrJmMOW+3=+u8fUDxKgH#l$is5xhrG3GSOQ`AZmPODU9dAZ+B$U*)I`)dJO2! zy{6%bG(}E;KI4eQ21pUlQHXTeGZ_m!iu?-tGDT!o#NWkA!tU`NGK=rQG14*hmcft8 z3>kVQa-(OQ7O4%oi7O(LM~U=IgD$D%CeZy{5t$)MInKKS44$JHZ&;T5g7@3k}IOZBSi++b3`5m zz1kIdy11bs9UYNZLBH;bFz2)_L%(&*{Sfq*t_V|3iwryEi2MUOfT>A!ni;1>hJWq2 zE*o?uS44#|dm;ibvS_LfV>8elT@e)kDKZMja;sz*0D7b=q5>dAMt66#JOKJpS40Is zij0}=h-?J?sw<)bAVtPL;)omr{h=$O0w6{1UhRnd1o|IWLdACX8}KdVwC`il_ick%@gBktv`ba79!Aq{uyMhiKQW1-;P~ zQ3068ss6!CXxWQd+}IELFh$gGev#~)5AeN{{Ws2m`QBk;DmrOIsR)Zg-8ynPCuFbbN>w=?nVKYeae@I`-m0 zj=A@Op8r3IEO~gC*77XqZC8otx&0PM*h}BT&0ZRG95NqYB`4yor$J=J=MykCm=V8# z{?8SWBOvq5VGvn4coOIT5N`eWQQ1#AriSCJ!H`*%j@*%I>O-a_<(PKb7%8$k1&KA8 zx02gH557v3$UKWV%w7{24SF)D1+IppY)Lk!Oq$HZSlf?+PeEvhD|qs1!T8Fa5L|Z< zwlf!ucOm$JBP`;4re!~|2x@qp@gtbu$?~3y!?Nz|hd;CKJxa5wDX;-QidEM>m4=W@ z&6UB_AS(x&y7uXhop#%S>Eg2S`UtMQ{$4m;4#UA<#yG5Ys1(^yc8nI83wp&>BHF7` zZetCYAyvH$ncc3O8X{8UxweRq6nP)?*H?*XRh_26s!ekoRsTUIDbeuZOr zIndRw61h^<=B;p@Y_ct6ZgAz4RZ`UpAHx$;WH{)_SBYpwTIkH~aiYASZ!C#;ZLoHpd{H|nP{RIOQf1Qn~4?jwV zR;$?}^BL;dT4^F=a=}-1WmIxXdRwnCpqqi}b``Bnd5=@Y_J$oY3i z<2%7jN9}#Z%#6KYc0S8%mZNs9%fugK1EwM=w*oR7T{+(Rl)jRD zrfR>FHVV3Sx;!tz-?d>O_YLY&j>B-fx(64Dl*J=iW(s=o$8KQhGvylF`!C8#%qiQ; z3vDmUrDe74Ersiovhh*oMPy5s(X*qD*8i7ZvnN(r56-m{gI?kf;#Kc?6y|^v7~9?jiCC=y>k7BV!$RFe~cN_ercJUSlw1Cb)90%_1)4 z`iw=MNV)ltS?kKVmWuf2^yz>SBedK$$Q*U$Xxf#Xk-`JB#%bZNAb9y|;VU#R;@}@P z^lrVhNYBK&5I-vW?`Q6@4iV|S77t^A;~&?9F}0qkrh9l0(x-U^N%=TW zB|^pIW}8u6F<46e3XR~e^77)MrE~Sgd^u(Dg`9~wM?Zp>tjIuvC7LxdbqrOm)(xEgo z*m9D|lAoo$d}C@7=M>w^_H6G~lq>mRn%T*C3S?pL#w>pZQdIsPb`4sEKj{H5R_p>T zN@Ayr3riNJe2bMDZvsXU<<|oi-3{?0W$+ys!qspf^%yK?XP~Z{(FJAJAZ|Ei5p<1v z*la!JYIG9y#)=yI=b*B&Q;FWN@&QV=bSjl(%_eP8*>)C`tBU?Gsn&Q@$uZbj)Sib% z&O_ZJ5NRzH?Se?1WvD&{TkEbseRfaFau5Bo9U_hHM=#Au zyx24Ui^g|L=pjAIX_8J_uXPZmWj!T$$-ljOUZ^LsDo$P{Q);|Ad9k6nzw;jAT9^DTln>l{skWCQzk^>(LPHE=>J`|$szOu6w>@N}bzC{#19a3lI9L*H4- zHTJGi-6~4bg=~3&VvEAMvW}{>JonP3>oRn;%pGYDo(z8|kT#HOdH{t#MU%3aI0phZ z6V16B?LS4b1$LuT`=`T?DJ`%YojQQU)D}&ui`0QEhFf4aI&~0>X)UlDojRDsNDJ&n zrw(B;y#;ooQ-`t`Xo216)L|^zEx8+=I-F%F#%^@#XqNL^U^hDT5f;NOxf`82pXGQ< z?nb9BU^$}&ccW7mvYgq1yV0quS&pK!Ghkg5=Do6e}cxtk}Vdv04Jnwq8+)UY6|z31*qv-Dy*&y4s~?F2q`allPPu zVA*IO5B5Apx?Xlkn>ydXSH zn!r!BTd>H@Zma2SERyn_oQ=;b53KglqLcXX^8^30M{TDEys%PjqGOg8NoVjOMgMa| zr5dgRO?{xK+CKMG#F+G#LC2MRRV0E`?N|7E2jeC2cqcj!6ny|yK_gIq6n=+VW+S&7 z@N&LoEHtJ$U_%9cNN@Sh=Ih%*GKB{v1sanQ9v&zfXhPjkDi0Jrrj&NxN~MQz(++f1 zS|F~pbX((U>8`Z!K+(Vrk18$lK+#<6Q^K@9A^Z;UK+!;7sl{W75Dyd$^ixVP+Lh7) zJf&2bHc%<$fueyyA1bBtK+z#e=`5a7n#u!31GAMDzoX^8`k<7S`?Z$4pyh$8s803< zmI)UmYC74SgO zz%vRW)Nsp&&2-BM)^C*cJZ4UXX#I2(MV^)v*hJ?kKR-_?;o*Uzfz4wf0YA$FMeA8o z;W>fdp`4MRKbH#W=SqZMC+<%?Q6%5Poh)cwRyHxf|g(3c}C5 z2)|Vje(p>7or3W5P{Ioe!p}V1GVr~E@bexs?gg+|?Kl4<}z%L3aKmX2M^U#HC)c+yti~aoDH*~J_^IvqH^7Ca%2~Wq# zxZ>|KkO+J68h9Qkx&z}o%^RpGd>@;t!O`*Vi~*M5NmrXdJ=c(UNbdaT@-{mAH|{VfT!&A+S zMf8+(esjgp`{{CyY>K5E%F_KUrAyQ0gxN|8iYN~h4YW2|KnM{~2Z}ZfNWBw{e=!rO z2;8GvbRsZGV_lLW#!dw0YOEsgu)&uvs0ciwnBoY`GfpBrDgq0n zOH~9GN211B{I#Bd7R$~}j z5tEz9k?=G~q?@uwc#BMg2a4i7_Ns^QaGZQh^YCCF@)??k2g{I;YaSjNLOxUT@K7H4 z5}JnxMv*V6d3d0Zd@0R`M1%*5;{Eoj{UByR@})IzHS+EVz~izpy=Xce4`k;62w-M zWs%{10AQQR-EAX-2Z{!^n`;5gj4Fcxc9>5AcrtjPXke$g0l=Ga>S=&o=4OCE1`iYs zyk>3z2xjm=(ZFtVJ3u&t2Z{#vnA{bQX7E7Kz+Uqt0A7j91!bHIz<92S53aZ3TrS0V zFOTy+6X#SH=Vbg}I9^FTgQPck95FB5_+%_knh=VtXSOZkCz79R6*Qx|HgL{ zySaoW&WPFy>+KebwMFR9vVbiW42aNF*lD*?!an>7BbMiO8^wA>XjmFxTg94KfbrUP ziiNY}>d5Yp2K(i$+U`h7cwR&2>`v@4x;lMvHqOKd$*#^=j^C=QGnE#ntFshzx;k4z zx2yLl*6Hd43OZe#BO$vg`}UAxoxaUetkbtg6pOye&MZ*S?aZTpyPbKAl<+Kt`Szkq zsx$leY<^yf?9Bdg_^mqghSK76=1m2i&K!`??aU#?qBH+7Zif}b8toT)_iYJH9G5EqHvd)FvlM#Mym)8+G!!B&*?C*fpSYjMv`o?%_Y;|y$qJ)`5t*1F&0{u` zJxtLU_k#)e){i&lOT#>vtyYu)PE#0tj@(b2u5l918KitvW6Vy{2{DD?g-BTpMZ8I0 zb<`sw(hYHqO%aiP$kZ5)kSiU#r12C&Cub+Slq5xT8)K0$mV$sUx*GGNn5M$g7u}4% z>5DvkO~tG8Ra@u_pUC0W`3h%<67uwio(i)s^ss%C=HX)1b}!>aC{u0UB1sWlh_>uo zjVD2%?GZ*E@C&N#k;W1fRNJGqF0_3oQ)P_CxUX`yvBzqRyTyCWH`DL-v#XDXIJ-3%? z-MGX3%p6*-F>LKjjVm?AJzd(mN@3UTestDXSZ_$%o%NM#`&-5U$SJ?7#gvH7qOC`an?S&?=M6sjoULsC#u$b| z#Z10r@bPun zuzlu>kUkEOX4rmnD+;RZfH@b0f%~4;Wt*!&DqTsE6w#N#+R5g85Mk5KG?(Cuz;npH zG}A6&dQniiN}7uyi111#VODmT(uxUrM2VJoiESALaqp#yY_o?eSoUhca#soFnj>7n zJjJjr<%3e@w=l2dr~xoFOBz*jGo6(q%_uptB+B`+CDpeAsX#=Rp)WW(;SBp`;B14P zaXhI-Gw@SK^Ha80f%($uT0eC*-vp_2bvnS@4B)mmboDmdqEMm( zUgvd(QibPOCAtCj(a;hs4mtRGrqKCsm87? z%gjGqTb4^wL>F_ct}wq-wrn=v;(89ZN!ap&`LAosi&~ds%S#$Nw!Ew{Z0Xt)ubkha zF>HCxL<_HIjJwZ8&cd&1jJuDtb(_Ynt=r96Xk5i?ha^Sx2yC-=n&UtqW+%<3kaE+N zt?!wGP>|ViN~_Y@@xF#mc6@McOCOp=xKy?Dk#6Z3XvV<-Cq7|E_2)dMUo`2krwI$V)0p-dMVM&VU6tr!pd2A4{CC@V( zb7C#5TVYGSCxL>pr9kU)Y$>m?V@m~%o$RQnv6CH@GrLCMh+G$lfJKAgLWJkwqTk7QLh)b1MI_s8#Y^jT< z2?%)Q4o^GWi%Ve*2Cww-m?)_1=<7D6vZG&dTQWQPYwTplK#kpA4)Sbu+a4@Q5#`Z) z_7Kko)%GM$8_Z)*tF|Y5xRt0PGDYihA~IEDCnD1{cCur-#!hz3)Y!FUmZv6^D?iMZ zq=>fT9D1*(00jK7%<~V{INflYfFG87>Y<=)S)p|~wyf0Hv1OIUPIj!;*vXDH8avss zR%0hS)@kh8`h;hXYwMGe6w&{<{(8#u5^Xi@*E~OC-I0a0DQ=&;Jw6m77r55g<5>(f zd=Gl$b*_T;YK+xj10-n(NagppC5dMQu-!i5xg7-h@~!7ST=|Xa z%Xgl4+`e4Uy3m&_-hsc@*y+m;8ix?4HaJG)qQ*hoPXI4zn5?_@lg3Whe%2UWlU?~$ zV}!Le?f}1O==S6fPhFU%dh(|vMU;OGWdG%<1Oh$D@ODL%YGHICDsgWDg-DEEF5y*C zao6Cbye3GcDN|MMekPXI?ww@C9Mly;iC+kRG@UjE3&Q1 zZd)aqbw@v{Xbi8k>4w8us%i|kNUs)YjOeR~RrhvuZL1+kd_Q0=)but1fpu(KFIQa+ zF?z5DZ|BWLL4Aj8?^WNEobQkwG{$$xL%723s4*^3ZFTm3>$cTJk|K&*7uHbTGpemV z-Z|JrTdLaX>z(Gd)$f|N`nzpu-2=Tn*bbj=+k>?3hoH+I?B%3`evI?-AVmv5=*M{P z1y}ckYjjU^bw}D3Lc={8Q@_me$=(;;wx;N|5}fI#dY@EnJ?t%jhexWm9`W`>LHTU{ zHEk`prmcn7w)L2|3@%pvTBO^mz_Gj7n+5{?dfJ;;R*1hEJk1t?w@geW+C`39iz=ySNq>41{ErpX{nr!=s=J6E>>r|WqrFnNa9{0we zOtpPNk|H{jQ_{QM00^}GwYLw((n;0!dG8LkE!+A=>EhQdsrx&Pu|QVg{N6j?)%}Ck z-4D9#i{4q(ZQ!(nOZXn2osE7Owy^vtM804U3`;I+ioZ^o*7vS1k0eF(CtQmI4?b18 z(yVuI`7os`Vs&$MrC+NnYF!6X^*N?>oj?taASlEy^f|}sg$40e0QfuCT8)CTE6`vb{p#$^mL{!!)|NUK_N1blX^SVM=S%it`1gdkjk!(x{t?EgGY@# zRu#H>S$=qW1psv2V$DQB>ALk=UAJ3lCn!%H3?Rzc0F)t>ceB1X~sQ?)nJa5*% z---gnyRwV%K?PXRGKtTC)xm61ws=U3zst2Hby3)EHAVYb3mDLKv9)eS)V^l_^vKtj2GopmdK_URK=9{}ysCoLWcT3*EYxIE4$fbpsZ zKKSij`G()rREeu{RpR<6&fB2!7iZKsr;O+kdgUpr58Q+t++elE3^^jt@ybSvW$l&c ztg!&vE1Rr|06GVsx26K<9NcWp0thL8ym1x>y#S#7wcX;uXxd*ptQ`P42X|U~018zO?y}wh zKo0U*eVorLm2>!%OXUrpN+|#F8>lMr+lDG}r55MyUtPvKMVwQof}CKY?JRirHETQ~ z2Jh~(>SK|1G~e;=ev4)8-8Zav0kn7Dv`zzP?;fzu00cASbEJdTIe-+EfQPKF0aBH# z4_g-iw5#8;egx32e%tyDK)d>gbs0dr`luxeTvs2nECB85cdR4;?ds!JDu8zN2`dVa ztw#8}RtW&@-IG=sfQrhy?^!tj@GdtC;(X$&{KDscaXui6^Lccf4_mZ5-NDT-QL2s$ z*f>``@hs*zZzl0Cc^RkNXhR>od&)Y6D28j=A6kQ+#+zo*XvzPe%Kpgefut@uiZ`W? ztzig3dbiGPaDbx4Q#?z4!q9wTm502D4#t%@VWlQOsVWGekyN-C<-}kw*aW|682SbD z$)&yJQ6=Bt@_+CJ^d7!|KKVKtp`^bEPkv?*?fD7$`hVsH^qvnej+3`nMJwtB^vQ=(D&Zjl-{6w`7M-VF zK%cBOC*=$1laJ6S^#b~2xl5^DK%ab!gGjxAKKUIcih2Qk@^L1)dI5d%2|Cz$0e!GS zWi<9bynw#65i0e%jsHJQ`XS5|BJmA|jv+kzQ5!15%OF$v0P=GLWuC>{AQGEF8i}=- zhD_l(1TIvqi;}EaFM$6#MaeFhazvuLM`~+;+E5*yya{df_&*M}Qs#5?9`C15mNK(Y z8)~>($u#bQ${#3`DfO(!NH7v!SZE~<;I8dUY=LIK@N|P*sO3I&Rh!%A!M}yLYB+i! z5|i1N#6$Qr6D#rQ5uQ6B5$gD-lJ9ci1pWgA<-fumN+f>4r;(_Fw$QI1z=dw802Vg) z%mX!ylHDO_B+lTb2W(#*o5>z0-7Pi|K}5$dKog=W3zFe3_V;}6B#FxP<@g`QI_?g1=UeD+Tr>h z_$fz}BkA1EjNoIn5Nl%ysHrZ^)XAY|avp~okvoTpv*-s3E`-o?t{|hC!?5QtlX93O zB6kq_8CqNowilpx{4zra`RdLWEGm# z6t%63nFRCdnOAxDz6G^+J4_B!R)!{r$tXiAa^IyP&-O-^7!N{nnJdi!p;O~wwzc5^ z++b`1|FR<^az9~yZaj}q;~;8}7Bj8ry5~~xX`Dmt`C{fTgfO&e02BOg)cT8@ZZpS3 z-dK#I(DNTdh}g&io#%*%T>i01X!ClSavf@$J50`8`Yd-_3g{Omz;i}VP<>sRy%D)J z@DX}(T`K5tpk}zVygILaHt3h$K*$zD&{zg~jUyuRdXjy)KEq0{Zw2#OF?#`Zp)GeX zCCHuv^Kmh|8k1h=mA;sGCHo7Qzlzy^SpVwl@Q7q1)v!3lk4y%Udk*G?wjbe8D@1J_ zhtXYrk8{C}0WjKV2dallt6_bKS+pw!%RXZWs1Xh=au2X4uZ_Z5&zObU2aA~{jQ8#d z9BQjj%l{;(ZQ*~X5AEqt7R*-EzE;fK%bxG8z`=e3wWo`jV|4oKvl+4rsQukxl>K=Y zXOewgnMib8YITfy{1lIb98QZO??XCi{|q{Va{S*YO|Oy@dCQnOZ=A-oB1LWn-TxYq zk(_znM7qc6}s6W=yVdsFEU(CLp4)&cA@R*#Vo(1!KG25Gw zIDQURaqt)iz#MVe{HgTPd;cO7WWNA$(IM5OlK&U&K2;sFCll3&J5~mMRM=Ug#0s`C zOW)_4yYd_wUs}BU!ee{0kQqsAAp1D{9`IEC2QpbNVW@a+km;Y*DvELsj(%^}K={{l zBWD$>Eag4bC~i#0$0GccBa*G=Oo4Wlo=UKu6kHE}vm+?V^MR?SVM~1OL*;3QxK=}f zhvqctfnoaf|0aX3Gz6FJ&BkrObIZg!=mp;~<(a@cxyagti#-$BQE%4RG?edQ*~)qW zvGGh|*_X8kvGh#g9PiJ%fK2sFw^%rIg&&)F@Cucp2 z4D-yQ$AV>PgXcDyU@WhN498D7q8z!X;I+~->chRIh`fv-uDe5^ohbA0eO!0Wy_T1W zyzU6Or_XkDW-*}g7ig=tqn=fGdO7Ai|PE?Pfc6l-LA5{)} zzATvMQM;v>;oE^cckYXVIfU9{E>nST2J+m+KWZ^PN9{K*lgrII&&c#_F#n)70OxA^ zk#-`t7aJS31p~<7|8OgC>A7GO5n6Bw2^fw|pbMZuE8 zAja`|{+&)`j`RqU&x1%*oIMWe6*|6=$US5K*{6vg&Fj#u||PtUT<&MrGFFuMaw-X)6& zN|3Z9NlQ``F_BeF7(i4&z$^#~h++a%ykf?j6$1*Q7_I^3ngb%{boKguo^z^u27d3) zA3t8NS?cNM^r=&)s;gt2gF^jpQ8*HXzAQ{eVI~WwqOh8Ub5VGKg~cfRjY7BLW?0p| z3`nC9LnCI9-dIZQjL|LKxyYDXyK^yav+i7iO^AOzI5eCd({ILoCZMzCMC^Vxem%L| zolbIUO%IL`XTZ4-!cc_JQV4vGU$0Q8?;fnf{uM5825`8z%cl3f0@A$H>$3(0UU|NV z9bl5v$@IAmn|R6jfovKbJIlmP?~T~Vt47mA}O$8ENnjqXxB1hMu|kwX8-haHC%D znjV~HoMVa6LdahO*+xC~@l@ZL=wRnq4!{?%b3Y1q!mt0;+%78@YdEy|59d>C`U6S^ z%+KF6LG~g$a5=Vr0X_IP$VFH1pNpR}Wl&*0JPkhM1n0~$w}gYMGc3CSzo?7;fFkXp zS=vRXi7Ca{1K0J&nX?GeVhT5jbrbr9MKLAw9Su-ZGNH`5y}O`D$C@6TMV*C|slv}$ z^AI$?fnVNOiVT+uE;Bti1_kj@SJxA|hDDdvW^x!$r zd7&0~1fa8KFLZ3}mFI+eB0Vpxg2V@aL#mn?vjRegooSpGS@?_EkA@Q7E%lj>0-I6; zhR6L`;mGeZ+cGC86Ft4GJ(5-zAf1R-p<1f~gm@z!XS$R~(xqUqpo~D&?W;V5)sGVBQ z+YM?tjW?|2tX?*bll&M?`SBR;!Ygm;#=Y|9Z?-jlOB-W;f?5cO_w9-d zgDfV-_w8niPG+&-NJcX#n#nR0Bbq_cES6i1M>K?b&= zd~tsrPEJREh1ycpoXMMi26r^SfPbXKKV~B1>lZhZt!qi~S*kJT4(G(xYa;$?bbvRY zoY4X1Hz#e(=H=*04VWKm2kgDY{`53pzNZ26Jq?)eGhn`#7fHacm_%8PB;aYle2FCB zw>po6MiTJyA_@2huTbrM8iLo@`Ee@YgcI;jjCC`Xe!?s8p2LPZ1s(+oyzTglx-=fZ zPJlvgk-dLFLH5R>_7}>@miU8RxIOkO=GAzc@hmbXLA>kfEOs7%V!z8!MC%wqz|#l< zo<=170qW zFXqaZpqIkNrkD#~fvaTuS8m3^VvanPVb_c^5LtXN92O~)7 zf~;WVY?RSdS&-E-CQZGt2>)wS7pj)9sf!ebO|@VY=OMJi6F z0N>DkW2TrZk%Aox(NSE86uhZ0YTMgAVX(IC9a2UXWCj23gw6H5Ko?}y^)c^xLBjb7 ztxU_PEO1m&6O)!qmVueHd_#OJ$`%$`+`y!{AS)=g^2H{-rZI4d zVzfEU1zAC<#dS=Y3$lW=#R-!ZC)8IAFQmC3D=1Tpb!lmFLj#LllNLWTv=~jUFP)rm z8liFZ`9WS#E~F{rf~=szsS5(W&;?mcYyn@4aZW`c%>`M(II9b7;exE-aEr^3LuGi4 z3C1gCTi{?59BKJvSoZ{npHphxM+<4nu7+$d(P5+l)U6A$THvTf-KRTzuBLU*vbs<= z7i0xzT3m(?S$PznWpRCz<|3!y9K~1#qqfbqIJ9k!m5*$j>)aCAcAk)?j0>`Y^Bulw9erE@!N~K?g6AzppK?J~u-Rhxl?$?h7cGYET#yyKY;nrkzQy9m_E(+vBHOnL zY04HAW6y2QR<&IhWc{wTf9>p|?ffPy_(pZ%3&AuOWCgn|hM%|~EBMx892;Da73{GX zV^96|owEYU)Ngx*G-X_n6@2gTjZr-(&;?mFxT`63g1}`+eXSb_EZ{C#kfpi`+!Bzg ztB#PSY!gR$p^LOTrk)$GA^H%p?ig?aBq&7tTM?M;y%?PFpok^ zNmNnkZixh&?km`AAHf#xr;%VwWmuQmUG7c<*^mpef+k{ALoUb)nu{3?xgaZOB{gZ= zT8jcx#syhHmCM(C@RKgcI+<;Af)VZ*6w>^VCK$QDpK9GhK&q}$)=ylJ6^wS;~K~^x$ovk(L zf~?V)Ct>w$_Yf4)T#yyaiKOwQQatG5|pbSt{2jjaY0tF#ytiEJgy6}F2g(tKiub@j)K~9ztt7m@_@ymEt@QcEnJWl zJZLd&xr?Xdhb+d~hYPZThb_k0M{Ir6;>gy=+}|Qw9~aV;ZNqpEo^ZcWTXjL!&uZ)2 z?gzA$qvIW`%8rhITNsXx_x7*peRmypRj+(tYvO{eV5hqh1iYdPvQEP&hFA8uN1&ji zXOkh#o};uOtUy@<@8uvo*ku?GlWFaSf2M! zj5P*`Yi(=QQExI7caX30|wm2Lew^$sGj&&AC zwyuvIh|1M(w+d;>xF9RIE!GMI&cM1LYdKDSIDI}Hn}b4{3$lV|VsZwCBh%0ED(G2@ zaW%*VS;2D_Crz3QvVzTuaa)zL%NLk57i0x5T8t|XF31XAvN*u10=X)(7~_u% zvVtuZ^9ob0!e5Q;irTVONK?iIS;4m04sDAr$dd5&Zm>JnA8NHN-&$R0OA{Qx!5)jl zwtQ!C5@QAnvVy%9*Twk+@OujjZPR|VIBeQa7Ncp>lwT}Hw_-t7@T-MUOMZ{>rLXqN zA3~ZkF31Z0jNJ$Vy`l@UHlP9Ml?L8YwuFnMf<~V93XeqbO1a0Ek*cdgNK?iISwYsD z4g$J#K~@dsap-E}@ilIm3$lW?Ru{a&1zABmi{TZit9?{g11`u4I#>*^a6wkk(PFqo zyxPfPo~^{T&fc?;Z3ha8`vZ=JF5V{E<^{SS>t5RC1w*}6v~6G|B!+qW-a`(z826A{ zFuH>g7UQ_nx@tWJELJ~^64I1m1FoUGTKtc?bU{{K_!)Ig@)$y2>zce@T~ngEtnO*v zmPq$>tD6h5f*IZus#_Oi%~svBy<<^O-E;QSeQu;X&D9mbT#KW2obR>7&f1O(Y+V(c z>E?M2L7*MFAnP-&>niWnsIF!E)wO)Tx~|^8t`*+0sIHZ^E-uIlR(XrGE?tnt_44r9 z29J3a(_Cy3+@ZR#AS*qAv%#HKcRd~Q8!ap`X)cNi?y?xSmRyh(+^v`kvb6i|_4omf zHv2vyF;tpj&-=aa)f8Qj#pUuaWsA3irVM8XzhZUcaf6uls$wk2(z>@<9=AZaPBp=H z%SVUf8{Q>QrgiTS(v&U4_zd3k7~dZ**9BRFaIuQIzw$bupmlw%x_G-Kx_4U~wQG;( zL0ENvXLWNyRZ<26Rj2AI-CtMQ=cTvWRp08`Q3+jT{!P^71-c-sEuIsh%`N5L1qR9APu2Bg~6Lr7CL zgl+8UcLTx88CmP}Jayr6#^=Ya>1mwQhiV()M5}AKe^sPwgl!`iWCbJrg{n&zWTns& z=sMc}HPSV4e_hA=J0o4kSzTO^6&&v~ia+eq1z9{8pz9RB9|~&Msr&0X-LInW{TTp>jNJS$^iKh( zo8f}2V39uypg8l+?Es7Y*#PMb7i0w&`R4=F&oC5OaIw!A_GK9^$ORbtSNPWhRAjgyE4b3X8K5#F2jUX{R)7{6 z8O=-me*siwxF9RI%6}T5I>QB7!7_g{Kqphq=iB9chE~1~jVV>Gl2wfV6shjei$__2~`%{Qza^?Hm1v0jy7N@}B@`sNTNW ze-^;{^cMd`0PEAW{;L2L>iTv5>j2iL>;1O@tWR(C-v_8N<$PRT&L@E7e9chKyLa^s z@6@!!t8y*z`ly_zLG>4B)N)Q4W!vbL+x)lTCX7K{ko75^b*NW1`Yc=@kS7Xny+J?Iw$*fIE! zUmw8w>tR0wVEy%o&sBML3_j|&0I>dg%&!Kp{(9W+0AR=96aIk!?Q{%2=^qS$G0122 z<$PYL&f!xo9XEU`q5k6?sFrxQp(S3amGktkyYWm>&Z$!&CzvuW$O@kFccaJPU0smH zW$EhO%|6T4yD#_y0jzgl^oIgi@4n>M0@TgObEKF3aR5a+0Jr!@0i@K`ulUCTSXaO5 zPX@5A-s;Z)u&&@|OX$QSZL(uLOX1`Ldv#Ph8b6eC}7y2V~`Z`&G_|E!Lg5ywwtKqO`;d*m7R= zlpjoCo=nQev&1R4j1PN*cl;sf#d=)=U6A!TDsA`=Cx8$9E%>h?7i0xH{axsS`g~Iw zeCYSW4h^{=EBMI29`dG)3$lV;{_Ox2Phv)L64_&Lb(WQNS6RuNo#j&iC(DNfZgwU9 z#f{EcTNb9PoTXJ;jIc2+WHXC-rXRx)R28Fs!jdj<~8G~R-tvcw@j zuwKcWo#T-e|{pXnX|K+IXi1JXUn>)#Dp2} zO+^dX=q4sVMSEr4Rd%66yH=q>Co7q=vn#MAmX*xeS;?H8y%$^D?4z<>GiPTtb9PoU zXJ?;)K3K1rv$L8xJNpyrn(t-*!hZ|AtY*&6R$vla5YHZ@_G;$rYz+?C`E{~3bGEFz zN-S&yofWd~DzW%G+AHg>vXvNdCff>sovdcgmUUN&%eO$Lv6GN>R~O*ve^%CAWhHZV zRx)R2C3ALGGG}MM!i3>xC3ALGGG}Kcb9PoTXJ=y=zIC#aIXl}N<+@qPoSp5Da#2mR1jY?E96-z>1M%Jxl=Iq3F9z?~JeXvvFbqBd&hCb?=Qh{O*#rqU zrkS(3M~f3q#U7G5`_W2#JBwe-9oTMKQEfqwPf>Q>#MY0<5GCIMYw4as{|M^ui2gda zcQ2t!Fsv)^)4liR=-xti0@Wj;|H;vPgdPd%sEFpe8`D}$>nAi{)y;|M?O-k4U+61A z-4M}}z$W>}%G8L=ec+#sWLoYgGeBhC2LE{^Loep*87MM;fG=nkwsYZrGJ`}W3%-3M zvtmD)!6MTa{HRE#jk9lELqui@__HFJ=8;S*&7A!h6g!uKzb2Gv$#$8lT;^=L!PyA< z;ZP*WW|^v7=4@hTJLtD5BBP=zmpOY>N3eUq{2nQgu2&JsoGl{7&2iSjFK_Uuh-A(d zkpn>=8i~jVQ4z_UEh1bZe0(G#qeMj{bGC@g0lg>^k&#lh?hN#aWX_(%#;gH-dnBUf ziil*+7LlhxzY>YaSXV8QIa@?N0lg;@kuj$tk~v#M{1!NT@zX|glTi`LoGl_%pbv~h zw0p!B$($`BLqQ)NiD>tTh-A(dkyAj=i9{CWDw53EBC-thnn;9W&e|fGvqfYR=%*tQ z4mm3#nX^UY-=IH8E9W)P??obV1XRCBEt)xd52(LM^Qq-7p@4k~y1W!MO{94}`*|DwjE%`#GF%ca@x%zBAK&A z5+lJjtk$hE>Ia}mfK&E3Pr&ft7$($`BgFqj#kBC(@X*R5q%-Pc`(MP93=G;h5 zN0x|4=4=sJ4tniABC4u7FLU-o;9sPSj6ShkTBtIbIs1L^-$XLBTBpeB4Lm|MbN2th z7qkoY=-?DuGiPT(wcm%fro7GBL^Egi1wSa1G1YrH|7zy!3D|mkj=AtzFq%30ENq<{ zF;$nb=OlCXLiB-iHJH_8b<)pe&gO~6xev_45nG*?Ir~*?eS?gQ|LVNV*`H(U?ue<{ zxB&G@=4{R@ZVav|!cU#4eInN_k~v#MT7m8wiSU@P-8+2_R7vJ+p3>YAkU8f6DJPk; zMec0KTolRi)TjE|=4H-a8S&f&kAD(%%=6e*shP7sMA1}g=4=i@&$Qc$P4t;MuE2X2 z~{sB>%*p4$Pe0QMis?A?{ctA2c#&v)WGF#W<}rbM{1RaXLe! z7k({?bVw=vuF#AQaCAh|RYvLeggy<_+=$+uqu&>LDX8lrn!dMte<1YTpdO8AHrvuW zh2940-H4W+)VegNwPGRep&hsSLP%yMb9R1gKauO^_9)Kg;bY6LcXG|-4%;c$X8!|~5IaSP@?MmisVrM$&Q$i6_Rf|)oE19#|bmt;4%R)A}1v^*~ z$($`BcYxj$i7b>(5iOEATST^k-WiEdOOgY_s*=pvBKI?7yv||gQ&qm4WX=}33dppM z@Q^jQ1u4K*@xvL?wA(EqM`Hc}_$($|1 z&p`0)eTDNhGjp~pnX{)?!qPnu{3#SRRm`02O6F`~3o&~zM1al->Jo9CWX`7R+zy}* z*-u2gCYiJ8HFp%~qxTg#n3=O($($_{z-bYEDaRhSLG5w3;Gq>5Nq!xZ%-Pbywb*t) z_aG_vXF3qN7xuplTe{aRm;aKd$$v$a{O4=46s6IDiHJ8h&)L(wC#ow5?!DJ!v^vU#zcQUe$0UJ~1BC-<7^ zvUZ8>l)VyVH=7sRDK+9@m6zB~@ve}R*iKoA?Uc=n?UWk#rAkU{r#6%v3&l=0FSb)^ zLJ78`?GoGRD9W@hVeJyzDJ!v^vU#zcQj-o+d5P_G8RaFmQ&wU-WhJ&#HZQhQ>ZBf#R}FEO9I)Y8nMxWr;CsMK35npS63qP)BkW#sg6TwW%v5W(ltpAUg=U( z%~((=jRiFul9xo%Jb>)bU@WMV#)4V{er+gYsu>F^rLmwM!qz8p%pkf>V?n)+t?%R* z#)3*|EU0g=^_P%QgQ^${DkZU?IOY(64zDcnv(5gV<3nRXwZ_)YA)`L4W-O?b#)29M zYE(qCHKrQp8I#gjP*Xsi7SZbQVU?gI78Jh{axMYABor}KNR3o65{A!D1&SWqdA z1$79hnuylJnz5i#8VhPXsAEFfRKLUlsr3{%_F9p0@EKlH@dMsu&9@ zwfRCgL*!aQrqe!hri!tkQW6VFLh!Yfn! z>Zo4 zhqIP6StL}fCu2dSBo z&1iccr`gXqlNL88sBv0xm*Q4qAm+@3)>+g{WU9w=pVsXm>|Bhk%R|Nl z+y-i6NSms))L;ERcyZQdFt6lT-bNO;NrmhuU>E^FE3M*GJr zIvxISUHyE(SMb$P#Z(qRKKzS+qwlKuovI+7vCq&dD-{!|rjTfzlj7my zJbfcPV5K~f8UzWfJ5nc_Zj0taYV&_F?(h`H7l|2QPmLt1d$3zyDWSwdY+VvENe)v} zJ(BeH7fG)Lbyq|`L0WDRi@GlXEgpCQ^y`txikwJ~b3>7@K>rkpEX;}YoEnN0VqBNu zrvm}AU06}CZeg!<0DVX#LJyd>18C}7_wetKkir4aiMBwT(^3Am_ojg@q%R8OSyV^) z+upl?n>iB{cpOdz-g1=tyoNa!4&c_RX+*o z^({*MC8SqVhi3NQf%B=OWmCfe_3ka0+Q2w#Vl~E$#%};?VIlQB0w_u3o!dEzdJvwn z6rzl`Yo-AX`VaQT+0G1}VVr+)>($sgwa6X&o}w| z?dE>P;CX7u-;al1J#5E|K-A|9Kr8Tz>TC1^n%jlVy^j5HINyXF_#X zY~#u7FbNQ3x0)IrE8Rhp&+h2gG%NUffGT^m2>n4GX4*=apwrO9eJLYl;V< z<@iPBK0v)gmxJrZLwXnWZiP56;fKG40-G@ed+0bYtpR?v#NG=?lXGc3oYy0}Led7t`pyUfUGl%fKW!SSX&tSI#9$t%n zJ0ihtgDLVNw!x!%o%N>}TpJZ7DSlB;Bz_J(Fqs~xCKL}$ zX7dgM6qWSxVThH7W{i&g2KBF^!fzqY z>(bol{su~Z#MY^zq&F1&Ctt}UR3aU54m;vAz~PB?dM9=Y1nJ;TW_TK#*!BgoiR~ZW z44XJrt&mN%?1AAOu#MNfcjRsBifz1Ud(v(@3v&Iey4NFh!^YZ8*1I*l#2Jrm>fGNT zSbkVuy$7c`YgR%!f!>VzemeFzYI<|L#sxEYl5zfG7u|)e z!z=E=A*#dym6PIz`Mb5 z*Py^#yKy(7AmjWt6xd~5hN^=OG-DsZrW%2AN|^8%FzO%v9RBC1IWFWHnsKjSn^f@* z3Zn2M6sT})*EkrQH^mv4kO<*n#A#cY7&1BgBSjeVZgQ^jSD99iklZv z&1K|TY)LFl;J>_xYHlmcbl4Jn4aJDpc4!GM6@Nlcx(Cl7;UQEQ{?mAEt_D^^;I$d2 zoJno~IEjN6Yts(W5(h2T6&DLe;-JO)9iuuJcg?2-oAHa^g+CU*6=GNU&q9pVkCexB zsPc|t9`3S#Off?n3ocaLBE%`hT|(?Dt_iVc0?(63YAsxJx99ap;{Sqym2hUywWyVm z)Cw4~%Il@Du_<80D(_H%2v}9{QaNBBWgD6TMpE;5sfK-1rht*uJYHtu`}8{afCh7$ zH$d3}Q}9Pqz<~-A$go%lI7o%#$iIhEjyFVE&lE6{ns=D8E)uPC-=WH)J$1Og+8bWW zBG(amBS>i^HE$$ajHXH?wI5t*>V@y)e{JeQ)e<&!k;1U4iv>nay;#|>sh27Yn|irG zHdWeorLtk$mM9yx?J8x_Hfap6s4#5IO9G?DY*7}CVVp7V6@?8<0VAn-ykbMY6`6u-*~yYLM!K<`3;4RQ zh#^*xOaZ>3`^J#+p8d8%Av)?6G{}2XVbr#_6EIji>K#%>BB^=*{>#NZ5MmTM55t~! zJxq$8mvEj&At|G>z)?j_Oj3qr9g7>Aq>Rf##b{ts24>Ro4NX#7SY&YnlVl_{uh_~L zBa264;1b1XbCQwNyi$wn;K>B#(-tT2m;k1F^%cVlNk&rh$`m^>lN2{Ju-HYMefpuH z#V8lah|M^k!xKd^WXpv#DMnKBDx7ygz!w@xZLBZ87~}LnA<0N;-Z-lZZMmBLbGXH2 zrkIh`yzz?J7JAq_((*uB_XOt$I9BUET1b;(BsFiM^BD-#t&!Be*Sb%4{vFjl%j!bi zT%O^bX>plJGLo8imc{i=l9ANBa}?tNjoLQb;?TA^Rz9+At}_#rscq*8X;O@&=AG{x z2LiTfB(*CrqhO4zbY`KDWF$3jmFhyYvLqv^d8@7NMke`FCGhnY!&XL8^KP)Xp0)Kx z#jrKWNNV2AmdEt1ep~AlpdPhtosf7=%-&t^{H3;OB(=eT*!HB;5e2pFDb+>WCUK8v ztZvxGNNV157Q?TMq~<+uG5VB|)V$3W!>^26<-KSzY-c1j?`4Zq*7hwHN4CG}+#1=w zRY;R!BsFiF!JHt;JN$p^a0QhNy+XRIqSHOBB_xDq+>w{EXqpY78NzEJW{;s+-lG<9; zb)0)C3dMK;toOP?%i6q zMpFBi)_t|R425DwQuD5{y3kC<%JNoNjBuxnq~@)(*oPYsNzGejF=l-6!)l8oTds4v zLAiSTdLi*00*vt1xNShd4;o4BaLkkN!+mZq6x5dct*+3P2P_V4*<>+nVI(#0L5pF_ zT|65-WHHV@jHKp0Y%$J0V(X(8N47rZJ|EfoxR7{Lhw<(`;Xb6cY9zI1)YiA%+i5FD z$2(S)9UcF+FdQB4?O)UT?y1;Sz4C#riILR2o$d)B;1!Le))S)`UfJU|M?pu&cTrV3 zI`-!3lF{+K#o_4q(c-9;Ke_Kkb^k1+NimX|_lvt#>()qWFKgY2*gYs{j}*kNfEq?G z)6r4K;;=^wEe=OVU5mrfQDkvsODZ-F%GD3WLYmYCm9V8GHW&o_ppn$h#F-F&Xce1) zg4)vB>I!YCvN*J*+Tw6@w6QoG9c?WRM@Ku0!_m>f;>gyHv5zBLI|+$TeK=nq5PM5) z)kta|sjY{_UZAZU9Yd`uJ35A07>awO$vH2k26^*2J6wYJt z$_cT)DCp>z6ji08V{)!8868tB4oAl{i=$RfkNpbi^I{e&f>_{^|5~xfyDj!3ZFN13q;?EWemH$T9UFi`l9ANBXJT>&#tmZfIbH=lYcZ|{8A;81&f=s= zPUgI}Sut*_l8mJ0yi4ZeniM0cdD~()f(DHOCV-&$R03uAtHdn^vy@}0#=^b;bf zd3!Cci}MNK_ZAk~ru}Gf*tDN4M$@DzzgUcJMI<%vR|}(-{2n_89@dupA*4w$lA8Bt z>_iY~iAGX8Q(Mx&o4}UTrkCqKRS0QPjHKpey)Gc2OCzZjV;+ZB z+IYWF7bB^8ZLKbNWjlMgoyG8q)YU$!tC*40ybcz_D~zP(b+j065wCW#m}e`ot+RJ! zWZQv4;{JeRp^G=4wt1dLQag{fdEQWO5(;_`Im}y&LCi-RdJj3=V%$S+Au+;Y9Cun* ztyhhm)eobDG%0MrHI&D%CQ+A0QhOHwbxrb~MnUVEykA{YqPnc^Y2FG5tM2Jm_m#N$ z@@9CKsBVp47RsrA4e7}~YLYlcFS zQIfnnR2L$tB^k-YyVL5fr$c_Dg(W7*NNV0)7UR~Ek<`4q6*H2WcHh0;mdKR*gv3y3 ziaqc5o={UXlG?*+$`fwC-(|$1M=9Q;oOX^3mb=hBp?< z)D1g?G^vFcpWd4ulTpD98cD4b7pri?SKgnjTk85+b@6sfbnmt}YS$j`^+@-3R`+B+ z2-xc}^%qVS8cFR~>UKQi4@4o!*i)Y4UjcLTZl_$o9Z0n^CZtI*k{X_JHUR-$8cFR= z)m6`59_cFGUsu|n9qFoXb?vBxt}_25>he5|r1l$id0q?uqexdvUk*)1Qq#U`?Qf2B zRS9WQjHKpO`wvr>>uDsl{&?nuDX5#@1_f>7!M;pqjHITzy8Fc-wT(T5G$}?>^LqL* z5NM-DQd>%0j(3=UHg!$oq&`&J$Vh6cYq)=Oq-%t2;~N}PBmI%8OCza$pt_FspNn)& z++WwR{)R}`aaLCWd+B)pdexYK>BsFiA|0Rfe zT|AAX))vpKOBqScoA0x1N@dDe;CBM>N*PJbyU;%fAWgCY$z1G@04OVEBsK36e+)o_QbtnqF7?L)G%T$lbD2L8 zpiwC!sd<sc-F+9l0XhzfJE zO7n1%$MUR49=jtz>s*x695^XPQuCJk2cnPa;jHJs3OofDCF<>KeU`1aSNkXOYDK+$ zoqsAoLVbF@es5l z=~{mkK!v(~ozK@g)~D-zri8XWz16=Bpvt8AxIE1#fN8#VNb~MpeZxC7E%B;cOT0cx z^E9ab;*6T+l#$v-uiWO}0ykj{Y9zIL@T^0N|`-w9yH;6wh$0M=g*`(FT9 ze?8*w2C!rBQU7}Y>#xWBUjVGX9{2wQuw(EE{~v&MItHKgJ&a3?LEc!W`Mgq{!>3$2 zZunF}{l_~{E%9zcOT1D`^YpK~@l28C)TxjYOp1}zyr(3r9=xlO)RH(is&_a0EL-os z;Me0xQ@#75-vGdR_a(mqpl+!=M|#K;#cvB>UHz)x3BbB~tA7xH zb@evCJAifdYkqG4>+0=(4S;p^>;4b`>*_cB5dhZJJNz*Km3oA~>5m7n-hIoT2+&5o z`?h}q0KChW1!+EURlo4LUz!id(tP`s=ED~2&gkIgO_Xlq1#FsEJ?XbN6Yyk`=1a6R zr`!}Hsd?{6sJ+52o<>r;50#cMlA8B{zXJc2Fp`?L)4vl3O%Wrhc^~=(==KsuQu99Y zr$OGN7)j0BC1K?P*Y7@g20kXj)mg&zd-TBn@&d>2xeB5#U!L&|hu=#fUc&GNhkvL* zx2`FOR|ED@h<9llTLShI81wbDoZnyf#VeYU7GP^s7zebxE%OI%fmQMn#veq=#HPX` zfAEvo4Eru=I}@=Z)V@n^qJ5lt{mVp)UuX)hI|c9xt-~<|@0u3+H{#6sP83A2yxpgkOA8Hehzcz;d>+>ebUv~u*@Tp5dVQWa=s?ay}`C`MrT_Boa z>)5a@s^bn)CU!ft`u}=X>v(q2=|~o=bv!pMs^j^6>v&<`I$qkZj+YO>j@phbTE|7u z>c7$wo6(MsuRRx8!SDnh?fB$#ni@h#s1GqC@u9nA87xD=ZU9lyZo zHxD1aL2+Hjuj7nEA;};*exajPMo;?%C zT_tq6eueV`b?rV05?Mz^Kn(Zp(>Ow#D0XlsHPZ^zF3Kz!Hb+fBZDs$3)JAt zL=YZ^f&S&r9yNHabJ%J4=BAk#yw34aP=nXo3PXc$wKz2Rc8f!UH&`4Re22wq@J6RG zHPhg`mB<-H18`Qp}2Mc4ylYjqQ^Pf+EwmujC57lNA$gUqR6^8QJ3qt zasPWN&ia@r;jgwXPiV#c(dF&-d&B0pcYlvmb+B*G{>H9;M|U?>d45m#eW*T*syx4! zdvvJkP+J%Q*ZSV(xi6Ms=jVl5b)Lrw<}JW&rp@)k92PjRn_j_z)|j!NY!ZD zKz>~0k8u}(sF(4Na~GgfpT`_2mu>#>F3YBL+EhrL;JystmbT()WRklLz$?9)=f=tI z4gkOOxbyLMipx-Dak;wlr@A`<0=Z7|r@0>kB;?y7XJ;icM;-Bgk0F;zTH=pJf z0i@-Y#6KO@#spbs0}pTH=W&{W1S={!4RC zN%J^ObD*X-!%t}rGb#D(4(gYiGsmPGqMW*rN6ajDE1g~8&vsut5!b44pgMa_zO&EG zclO+TXP=kv?DO-TeSu45*4gv&ojuWND)al4}omu{jn zvNYc#SLJ(TS-wY>=X>Ppe2-k?QknJ0ihPf(blZcm9$A&|k!$lkvO3=**X4WU`h1V9 zaXUks^~eowH-NNw5G<_&oYahaTyPa;lgYFgLkF;hhGR{yMkw*hyw7 zh?0_dAlAF>;i{4`yo$Kh?G2%l9W3AGj)IJ72x0$rcOuGx7w`UGRImh>DG4v$V=Vrc zi~IP#U)9BPU)4R013TVZ<{!6_Ud_k*3XIj)tNFP7sxGZp^YQ*FT+b9tL_f!C1Ue-~ zt}WyCt2$gk^V%{#NLgG%-b2XM3w#P_3LYXHqRDa2=&j1d<9M_~pR z#H`rp+1_cSXW6)8F%qTr$AxO#wHTRF`{P129tq;-1Czi4Qb!-{Q1MUIC}Z z1B>xe=T7!l!eYGCX@dhR9)6sMOaGx52J!IYyt??%ir9Xf$6JAM#C7fdxD`kfhac+| z@WdQ1c6_uEmY8@w74*`C{Y>0`h37#~F1O+-=MMNn_B;hj9cjJ5Lk zdh0PZAp9Z^kL;JS2Kz;xi!aUEl0U-A!=W8$k^Mq1hF2NmS>I90g8Bcw@Hu%=_3t{~91P0j|?^oh3ZL1zmJ+O~&m-C^4vQS5|md(`5vZI4;` zux*c9K5W|)mJi$Zq{U&|!Y|#zw%IS;qP9J&^0~G>?=*q2+BW^n&7}TCuf5>Z1A(?> zTn3Qb)Is{K+&v40_D{j5o0uwpI{VT8!5?&54^@4BHv9 zFy34-ZQV$|g~d3;F)&-X47is3jWt&(gOO=_sHOW~wu1Md@it5I zsE)E2Q^mpLM_Y{E?L|DsV)X73j?A$Z^V?G5aTdda*AgFYF+Aw7MMqc+56)qI<1H@5 zcdyicq{aA7@dENkS&Y$f8}&`F7%$TJ;3R&u#h7aNz@Z=4&$oE?v?K9JmvP%v_fz(cV=~W>PrILh z!11)ry%WCwth0>1*W9yENG{-PvR!TFSE`o~ziu%`PnOobq1eS};Z=8hhhiRYH?Ylb zT8z;|bTG7Q{9TJNIxZr9&tmxWXzF|4VvLRxh(E9x zqhmVpPKz-*+Hn65Eyn2JGp6`1i{U#yV~YRBVmyB+BL3K7d^40L{={O;!#Mswcb}%G z_;f4&r7|uo=hLnDR~Ez4-Q>Sk?4f2pvx@JwIGWKvbBCf!bu{deF3=wPP6QF4hV9ww z9tt7!*x1-hm=Rlc5j)1kzB~}4kk72*hsV}pXiDPyv7-m!c(fQ9)ccPZi{sJatUe-& zA8B!gDIPa)430mGaq6!jKH6d&&vn>C6D>xMl@K3eG1~nKEj-p@^w=B3$61V*@_a@X zKi*q<+f#SEGZ28WjtaHt*TQ)7RlH`IYA ziAU6dCyO8gp70bhGxj}%;J}r!htN$^4-&PjVpS-p1Fy9eA_KiRaJ9vu1Fy3bBjXcHKx3)xbRz&%Rj9QaLa9-ONV+$$bY2YxStcss`f;)mE75P}0U-k+E< z8K?_WNx63z3i6CGUZLN2;FMoHq-MN{XDx;Uk0+J(7GqMcpgkQd#-#o^`HmK2YCV|t9AGgf z^)+mNXNxhZ-$Hz##hBD@Bkp3cPU_vfGuac2x*k778T2p~tJIo!4~wHoyQ}vMMuYZv zFX=+<@k2$>r2e9Py}bt@gdU&g9Rz&DA=2aXy{)WA?&dC3y=hz;U@R>5zKEEMl_^!` zGS6UV-RBBr>M66-%S6mo$}|L1a#0Hyu*ka~3QMkF`BJI2WI4-Aq$0hcST3s7di{pW zq`J}iYrI>rbDE(*!_>F)>aCwb_vUBnMrjQ;wJ_+g9DUtbeH zVln#bJK{$z#wFTM#E)5wOSIpKAGa8nXv~Qaf5Kv1qRp=Ye$ry}_hRCwEJlA{M*OtJ z=x;v5i9cg8F6pize%4|#V(F;mwkp;sB#g2Blxq z1t#?+TYIiQ2s@*-$fbzUQhKPgcAb9`nysx}ul0FoEuXsFs?auegMUpVc!x4si>yP}YsNr{j3+dzJRK8yGhi!rk25PxbhM)o}7 z&n(7xTTJ}9#hAM;C;q}>%w5ZfzqA;0*DB(#EXLgRIL|#_TZ|*)S>kUj#*y(7@otN8 zWNah;)?&te=$OqmJh| z%l&L|Gut`$YS&`^R>jgT8tikmvigE7NduD5g%ePdgu${?iQnm_7L~5*prqY z8sEW|pGM7nl)>DUyoP<(&tlXxk+WWn#n@BFb+7o1=pOa>KyjgZe2@qt_$;*yjxU1{ zJiaU*!%X#gU#WL_ygLfX0qpautzKLo%G23v6x+jjReW+Jd95-yoK_8A=>iwQkAy$R#AY3TAYV( zi^s4tTKihO3tInXKWXjucohoT+Sj!{oxAXe_zlIjwQt2oN0M(VqmvgT-%)H^`(FIK zNb-GUboPSe2a0WLKZ>t}B&IJgyOhbb_RaYJqSn4EW@>9c6hpMNA4^r*+D}A*Np)r4 zej5J)JJ*{ZFAVBpY)`4N@8sfj1D1`v1&$|!69M!saJ(ou6~LDlzwuPSFUR8Y4Q;$Q zm;;a~?MFYB1Q!6*EgeEoFIWgrT*|lN@zUTDfOP5Q96IUXN`Qv)vN&EpSPoDjuaV%<-ndYXE)tx-Z@= z_!Q+D`LH$KJopM=Y^l7rXc6oIm@J4y4H-QYt49Ba9&2!wPrM3Yvv4m;yFK&(R8gDP1l;qPuChuxQ_Npy4GOwUfL_^ zS~CmbEt8RSt(hxOb~BQ$H6!U-Gm@?~bFXZF6n|rxTN;bKnyxkTfFe!Tn$dKv8BN!k z(R8gDP1l;ybgdap*P79Etr<<%nyIM+opmz#=~{z@j8fM~(zOPQn+$@DlCCu)=~^?A zt~HaFt~I#)Pso=$fuw7_hw_rHHM226k4w7N%qu9zGLo(}^A*Z|M$)xrBwcH!egUSB zObh%i$Vj@@jHGMLNV?X{b`LXfM$)xrBwcGp(zRwJU28_twPxy}7i_xLU|k#7&`8p? z1{<0VhCM&R(epB2Rnp&*t~GNy%5Fx|wPqw;Yi4m1S|#aPGm@?~Bk5W*lCCu)=~^?A zt~Dd+S~DX#j*X;i4IX<8HCDWVQP?opvKlpJUn#-JewEHM*(B-;wys6d%Q9VSu#H9~ zvP{<+NW_!6S*B|Zw(}q=&h~+1@Hz)dz3dk(zrjJC&i1NAc?TU_26rbUSHk^l-jx^% zCi689L=)RgUpA%@kda&oJ1HZ%5;Br2A(NLYA#uQyDk-@V%n(S9l3|&bDedu&HiPQV5jO0p~PZ`OTkm0I7^yWDY(dv2Au)XnFl^8&Y zrPq$akYcpB#9J(yCfuG_ek01x!;pIpze=K}LN}{TfY#gx?||AJ(HuHW>6xZ$p~f`3 zya0ll``{l4H5wY~VQ)5Nw>RZTYRW-knlbl5LUSLqhh(ovn!VDLU1^$~h!K#`+y|q; z9}&u!W|stDH21+t*m`=78Gyqop}7wjf9>)d!`uf6&3$kaw%!^s%|9#zBe@UO(+f|6 zc|ON7_d!B(9|-#an2&R8cN{wj$$cQ~A7K8;vCMstklY8tHW&uq<0t+#&6)ckA-NBP zJqS#X9J>*xkc8wuxB|{_5ZJ*SnPZvzAR)OAE+Bh4nDaum=@r;ynltx7LUJF7`fEU6 z7mAo>%zcp1+y{4K>!uvT+y@EGeeg22eiAZGIb@}4nsP8omzrkGeUQ-H2fsoxK0NGp z9uRhDF!w=1b01{Lhcc!aa~~u$_dyqI?Ve)>(RG^pU<9^~%`wb=^$AOueW10IPA-NBPy#UOjh;7E)2MNu6a4oj33mMyF<~~Sh?t_OxJr~h>STpxQ zLUSLy18QeTn`X>?kkH%*-(%~qIfh|+5}Ny<&Pbe+@KYZ&WA1~5=00eFt!;A5MLZZZ z_ramqT9ae8!SFpG06a~~um_kplC zfLWJgnfo9ixetVW9L%#hmbniSlKVi|_rUDRvCMstklY8t{s!jn9LwAX3CVpRb5wmy zuI2byZ!q^kLUJGQ;BgKFb4bLtVD5v2ZHua&nMyHvTJcLX;k zyx|aNB-#E7s(%EPk!*jNg|t7T+5V~}On2#MjBN?iy^~FEBT>4gXxgq=0qM7{T94y` z`>p8-*>=|g7K}5dJ>zixN8)g{y^wx#1&g^qi}D5b5N@)Ok3_|;dX+{MqES7-7DNT;JQX!g>Ve>+WAiq(}fs=klgJV zS{J%uW8|Lp?)e@m_k6>Ex(C*|mDP`NMo@Sph0ju9x@bRPTz5YOf834=Qk z7Q9T)`8bmBw;irjUJeD?nl6l9>YVnT2;9312^Jnfu`2?Z)|v7(N<{~8ly*fl(>ha$ zQ(Y0ww9YgZi@PG4X`SgTmUKll(>gO)tk)H9yX&0DVrf@IGp%zHi;1p%yO}yCvsloL z%Uma|;emC;P=T+MRBu8d|{ z=O&iZ*gnkExtZnqT~b%0MX&Mz@MG)Yq%IA(VXJOnpLc1(4cl}BJGu)4pgOPV2KH{3 z^Os=5cHO`(?b4dNysjItM7HwaBag-Lj&XfRZ!m>zHj!@xT-gtQ@F?YI3{dAyMwa$t z?5Zw9xnYNH;BnB(W7!nr?BJQ2src*sK_&meU}qrJ+7{Gg`0@GJsql4_ zox<172bRnJX`qSc^K-23!yV8d=&d83cs9znhIB*fiY9qVJ;LD zPQ>=Qh3}q*GgjfCIT&<>Lm;0jEX2OWgKnl)Yq!VF2R_`E1(_{LNHttaZiqriGCJ0C;dHLjOSj>j$F@w>riOz6TQ<3ayF}9Trti(X+c?AsO_vdBujJB6TT+%gg;@#Intf72q-}@LA z85K0%hax!c&{y%kR0M^!FHs?vp2bJ228ckz$S)!dWA2GGj8zR+p`+sCxFeyc$D%aq5~~3tIesbktdDQAuJ>WmR-7#3tJb1D{F<%o9l~oBHa2Dd zAzZC6Ys$VMyiQ?-Df^l5dWGet?0!nF$1FoSTN!ctTA3*mZ&_3%6hhkE>0g(aq}knlEz#ip#} zWWd`Mrc7BG*$oQOy>QE&56~^Aar;KuUJu(Fc<~h|Yrw~5AiEyt%_;>^1_X^?T z`v`wf2p>O2$bY*!!u`V}23 zKK_$VR3HDB(k3~0n}Fd6ao!4{X{!6dzKh{g3y zM*Q8~;+8?`?6)WW?)zEQZ_Rss7GY z^pyC$Mj1N3+>5t&o&r-Lb74Pc7#v$6t{*7At&llnknCaVE#l!eSX4phxz5jcXrkVq zYikR=|Nrs!-C>jjc4l^FcUcBlaLJ&EC`d-Z1Og%|CJ;eDMMXft2V`XImU<{~U`$?VoFLsQvRS z4z+*2#i8~uusGEIg%*d}zsTZH`*SQd+P_3)lcDx6H8EEEC#l|uG1{N2csyXVKTmXP zv_D^RU>6(<3h#2Eg7%+QQ&ZqPj`x*kY-!N`NyMRVVrc&?;?OrSw0|-2b2dG+zkv98 zi=qAH#Kv85TtWM{62EBUq5b=bU$Pk5f0X!Ti=q8>#IINk?aw+I_*ILc{R@d-vl!aH zf_S~f(Ec*w|5yy|-%9+t#nAo(#BW#(?LS8Rrp44g@dk^H_TN@>Qqa_+Ts^*HVyyO` zQmYVSw7*g9!IqG||DNd9X#ai5;S|0<2H7_W6|`T_ucX15n~jT=#?l-H7qtf+3tTi9 z@B7qNGrnZwp}oTyUuEN=z2=Osw(-!;QH-y#@z73d#y7F?sQpyN*V=g0z7yk{+W3r9 zdottgJ31WpE+T-7IjtD<0Xp=GgvYny#yCmN*L?M3jiL{ zmmorAlAK~z>8k*AW?QU1@w&w|0I>{Tq4rkm>j2^z`or?p=$ioi%pC-e=-UC(8G60K zix>9*YY*_4egOb(__+e~FGo1wN-p5)E8qeu;LSeZ-6-J17;t?S$ZlbL1t33vOe5pFi)|-i8jOIrQ$S`F8h+%jO2C3x4K8B%32QZ9a&XP`y zxdDHh>^aa$9JT;?wU>07><)K*iNgirMVqRFJ0bmef#9#Yb{oJW3}k6KG5X1H)6jwjyWm)eYCKYBS5R909{ zOt(YwPbgqzJW)`~5ok`mRGLWuqBbA6CrU3FoI`UrjVJQz2_%#bov2nb85UjF*onYp zb(#oUWjfJb)#hx6PIQp4>ClOess$ocW)0h>lWGs3GczesXSFRrJo6WcwpBX-;IkF% zA$~o=0b4p?0|cyGKxqoMc0}6k)XNAb*J$wi&F)6pl$aW%#MB@qrUof7HAso6K}t*w zQetY55>tbem>Q(S)F36M1}QN$NQtRI>cbL>N{OjKYAOUM;;SAg%-?w+%1Vltbem>Q(S)F36M1}QN$NQtRI%9t9YjHyA&m>Q&vsX@w^8l;S= zLCTmKq>QOS%9t9YjHy9tDwHtWPZ?8#lrc3(H8eHw4_-}q#niwbpD#dOF*QhusXFlF*QgTQ-hQ-HAop# zgOo8fNEuUulrc3(8B>E)LsJ9)EPin%DW(SgIRhxKm>Q(S)F36M2B}V%AG8x&iHzR%peu3M8PRBGe~WN za5^Ps2B}>U&Zfl7ASGr7DKRrhiJ3vFfEKW32L5$JAVX5j4E&q=AzSJP4E$NC&+G6f zC1wVx;}O;=F*8VsnL$d-3{qldkP|l(z&Bn!cI*HllKNyLKV3nNuuONwP zs#<@Io0i&X;0=%qC91_2VCc4)a^$hN$b>Kcj5C1UuV9+TA>AK@i{}zDw(T!C59ovG zNAK!4Os!BIPxui7<@*5C$Y+%!MYu*d@8G~r&Kvz?zs}_=A0Vk_#8R5KOL|Y z(s#gzMlWH;p%lmIDqHG5B1P7pBbZz2#1&m-OP#@7SJ_f$FyB?S)EO*vl`VA!E4vQh zmO6ueSJ_f$FxbItsWY7IYPQrFZqrq^)EUg}V7Am5uHM0HsWV*F)oiIVT+`KTsWV)} zb#AFMT*|S-+y{-xIw$9}TYot!UUNOJ7^UVo=3W8p=Im%bhep?k{!{qbse4y^`WqFd z#=A4nogJ+EefV*D@Z(~sR&s%=>dt}bIA3AW6?cXniC?oP?kzBT;#08B;Jn+-(_E9bpN~p$5HXK@6+hD6Bk0d^BBYu6xZVyG934k zSK{{~hJ9}h#E#ElIPIOu^cORn^RDIfxeOP*`3zseaE-T|c`s$S?9FHRGKTBCa~Ph- zaJ_dRdFC_R&U=;DFK4)uH<;J2V7QC7AFp4@a5wKY@-JYxhxZ7tFJ!p4w>!gEGu+>s z%J5=_2YTI; z3?JsrBj@!DkN2vsLih%TCwbd4yn^A$-T;PgWO#};hPzr>0QRMZejRT z?^lLzWq7vtCDYu-@Y&vTynZ{w=X(iq-ofx3ZxiLYli^FfaZG;~!?+b?SWq6raVE8_UulHVL`uiEa$s0$`2N=H1NyKAY81*1@#xBMK5_|IM$6rU1 zz@CyMmxE0;yA9I>u40}^^#YB0;4WOi%!Ui;M?s|KJc$dVn9pGri~4pW(XG=qK)Q<*!N!JxpY%sqzTY>rczJB{Hs_yCOK zUdmvuz^Tl=jN$46r!sdQ!&Ny>W$t{2YjT{*+@%Z`aeav6E@QYK7jL$bJY<5BoE^W6-z^|E@Tz`rA}Lq};e z*X@9-=u8bhr1)Rwx`UYP|N85Rcnk?YnK%qV7t%Z4`QeZ4(1~{O;i?^07e0@B@O8BL zNPrG@Fu=YFPw=qA<8co@k4E78Jnq4_&j`{1k9*<=3CIOJ?uj2Ppy>0sCw_=xaWw&t zd+-&s9w?^l^SCEIT9VZ}NhaX+)U^mG7>XmD=5bGajJg?@5;=Ud>paTG?S%MKk`LxZ zeF2^p5D)erfDZ{hBf$6f8i$x?r5b4`y@B(^I<+SV?9lz+PBt@dp8+A7iA>RG$^N(v zF1F>xfw(xHaxU(N{!lRjs}9wk5ug7GIFiFzp!XZ#RKgC7?LzoT1cws-1~FAf#!e>u zp0NUF0Xn(kFrroen^0aIpjvzi%F7>vwOW5>S;8!b^gzV!gzEqcE0Gp2_9L%!!F`?u zHj~dHI}E3l%dXGu4slj!_`GI)ETa-G((-?no2X&87|^FhdRTh(h*cs zQ}#VK1~<@kRbS$Q*Q5Gi{7KZ-;4X!zxbx4^_%-9sSp?$wz~tohl?2UxEOwo^hhS|hD$cFb2e5tac8&55&sd3%{u0DTSiL~HyYdBnY+>0 zj$MO&jsFiHNsYCHaPeJNLI8ISemqWd;kdsY;kWSLe;hy19`P6WFIXG=dx&vPtlVDP zVH72Is{>oK@0B!8l}W6W=Onp#>_-h!h z`!iy=-Y_g>fj2N`pxt|yks;4I-iP}KI!1+)yqhWRH!$lYA18dkz>JeTh>6V_M5UeN z>nwex#Nq=!N%2#?N+9-j@s_50&!dqrtNSo0)#1Vw3SYt8k5C9y=i3h{%q6@e{*9F| zDEAwMiNaLphvy=OA5C>mXY!wzGo#$J+6hUsy{V*(5|!XAKD)XduyJ(EUg1^fQTr@Yc))>pars#l_NSE=y~i{2lWRM0y`T`k3-+?Q1w zbRtvkE0!lL*ZAFKdzx}z`&YT^8m#1NlFG@~vI_kqJ9zfiUIIM3^Wsp$lct`vJ4ClbjFD%!{wm_x$MQ61 z(IX@~cn;G;$>Wh{Y$KjAdP>AIPIqHi^fTV_v}3)FknG@@rdN<>7m`mmJb2YQyMXuv zgE@ymzNz}zh5~+~s;XfLC~td9KyB0{DeCjJZzp<))x8oH5tyRRHM%KNtf?s*eI>3Mr~> zg8W>UzN1qv3?%iP@*&dZ1?hWt=?cWu75K#&_ikMTXjPEj zbdPQhP+yQPaj)J6piO~mclSQs4xnA(^EANyx-&orc<95p^mym@c(?X=!^HuhUAItA zvTnf_-B%#&UB(~Y#oYTD;yMRDy8!vdn1Q?vc$|~n4ZOCFNjOz{oVPqqBJTH$;56X= z$q)y!$5H4eA(JVCgUM|YL5>NJ9ol2>^VoGN2aJa!+Xv)Rv$DtS_GgAJWPc7&QgGQfrp8(hq@lXhg~2l6btzwW(l{k$_oY(`*eL71;={G%xze!F0n}s2l zbBe?FJ;+JiA~1$^^aREllRt<|{u{rD_;06?fZ@Nx@V`!R?j&!Z66>2{?=Sfpi~P?V zWTwSwlHUMMylx<-fs{(T))UEO5G3CGDI(m!Bu?ye=6;JrApCrCMEFHx!p#i{Kf5R* z{Av(`qJggs;TlT#4T(Vb*P4j%@5Y4xG$h>e9+F8Zmn!6jS8NXq=|+ zi!;E|@DY3SINc2X3Mb3GmqgLxELQ2vRI)hZWP38c%3`d_ej)l_Yc#41ZFCqI}aG!tnu@kBRuHBx8!^_+w?*sH<-sE8+aP-`Nd?&=JN zrFzCp&&khZ6YMP6QN7*ON8}mZ3K#b<@|Z9ZFxuJ2$c^nrW`?C8JBjonUp6J50vW4tNZXtqfKer{J z+QVvq!atSOebD(A@tC@H!cUt-+dbXCNDc5m-diei?8%B z+ivrijn9t$UI#}EgAKzGWEjGnU^wi4G8}j=E{!$)9z6^UWBwB{j9U^hj5iD?Ux4IC zFeezM@~f-KF1$2N7|cVle|#0r2#pLUydN=~Xc*R?hvYMu6AV}EjFib+DZ`Zw87?0c zF)VD!Ap53&m0|dSm0rZ0U|4wy88)zD4>e?Xa8bnYFh9U*7*-pG51D)obAsXRHDq{+ zwRoo?!^U?ahWBoW7~VGwRg_^9a|Ut$?=h8NIFzLS$Q%mu@$5;2j(MPl*=P0~Vr6kN zCwu=zz@cCCvXdP}#?UW19^l`gKyjPC7N7Q74IKJKZ-SPJ`+vb|5il^5`&W>shWtQgbB&nSIZWO7rhzB`$Q~U^O zb{a449?5CcwTH!!Q`EJm#Zc$5lzT6WA*ZNsu*Hy5)HlT9T9IpzS{unVRPkWl$Tdt- zIr-_V`fw2ka!pjbRY9&eOP?k1jY zG4_SV5T9Ui!O0#;e4@p9=#_Ye#W^QCo_MCk6;5fuuIN7}S&Tc}QY!6ai*bh=N%=!- zXx!nZF@IEox~lH`V6h118JuTY7#VW`p<0jLex&i2HMGUW8XhhnkS?D zht*uR(^y_yE%$1!K=6F(uTpnKJddd93`;+J)ZWqOQuMWw9Xv0pHzJ;w8u7fKev5cs zQL7^!v+LvJzhf0&lkDJmUp21|<=NDT=RMUQF{WN0syM?U&qr3CXQ`TxB|CV&R}UaX zY51@aj{if%lU+i6{b(`vedbOC{>fr|wr_F(zf!_Z;a)1gs5c`*6;356>2CqF z-0b}-&2Od03e~J&wax#fO4Tb8>EHq1yCmo1iw!A2dI}th2K)|1<*~_5q>K@ z3}8oDI{4e@kpMf%(!sCS2Lg02+{u~@*@T7|yna6vs$J?enKCp7~_<#=|2MBvV zq3Ry*i5_oj9`8&ZZ!T_I#(senug96(<231UPQn8qVh1ty{xp8rZ#{N8k3Gg6&4_i# z=1yXWtyMYv7);apV+4bE(Ccu_aLLcc0rU=UNXZ)s`xw~VN!~=**FZQ9`TcOfeg>AE zulAslF6wUcad1mGY8@hI~VI%u$) zfh8DkjtAV`z@n4 z*m(BPb<_oP^273Gp-$|3TcJ+udt0GSem4A}PJS^k)XA>~hC2Dpz)&Z@8yM>34+BG; z$g5p(73yS*i4Aq~mw};9{x%S|b{RY2iW9eL89d>N6Az;@dcqZ_QOoy_qq1@b3gYTM zC_wH&fmvoc`O`Q!Jw=UVbg-S;1J99J9%BaE+lNxz@qG^Wt`_5t&vVV7o5caFWH^R* zwAh|B1v?px2Zn5lg><*^aVOi4xQD@UG*5*NwpB-=WFzO!>Lto7?blOMIr)8#uvVfoC|C`R)pMH4z4m7TU}Ve2XoZs zNbajuUxr2Q#gfX&H=+KQh`1RQtWtG#(7*7Qvoi(LAXCm7yV790s^B5D3sM?=JfePy zc*7N0M>fe?p@TkNQ7g$S{V#lD3i^=xhHprP^?lve2ldTUIQxba_R@@88%#V-XtFg_ z`bL8_<%$O{tBsLdZ>ymUOMT7TQcnIG-dNrhanRoqnwH!~uE3nEDD*deG&x9GjQ+NX zdQDl3{&qP@(iWq?^|xqD zjOFw)7+V?CXLsEJIZZje^-C;M^w~#JIe9vO2>J>=${C@jAa!Z){f0P!{W=i#D6>yd z82fdgBHlmvb$y#;50StPq@MG4$-Qz84rAhd!Ece!9?LywgNIpQh(Q5~Jri`qN16izO9Y z;IgaF6>-sTU(?T0ZZm#tzd%2$qTFv-tfim4sy9cx8}u~{i(cQd{lt?YBy`Zn7rIM5 zc+cTQ`_&oh<1y;_Dez4?>Uji^mqS z9GMTim~7oB^b4tvZ?UrTUtlr&i3(z|RZ%&~*l32OJ}F7%{?L7)41Ip$3%4o!=i%vFUJb4L-||9o{o68kyK9pp>fDkFLdDDF}4t?vxBIo zoeU4YBbI%Yyxk3ko=OMow;S$<7Gr*IPm-N&dh8fz;$8-GKHq&ja37n#k{=)3A1ix< zt)9EZRz-3Sh&5+e>c5Mma`G!kv8#v&J5muIx#ir6Cne&KZHy)yO$K)P@bb+RBv59T>}<_s3bUIQo;&Yg&ut77i}6y;$u zSQPsJpsH{lW3G;U2~bmbo*Gyj`wpNikBq^R*v|mX3bicfn%F-8b%lv6XK5_njt`SO zE)JH(0)RG!9T~GcRteCqu$XMu#%cgM73vssU91^E7ukBotCy_+wlDD6J-8v(380&t z0|zT&+XM6{3}>DjW4!=+7e=w1n_~R|`W8Bq`sUbP0R0PZP_|oQ!vF>rma<>n8XE~P zs8B(I+hU^u_9$#(vfE?h0EQIyVxf1$CIR4sBYd3l`265;!R$VZT6$a~dR&0HZxYI` zHPv)5k3-fyFv`J^=CK>Q$M70ER=y=Gc4w?F!i`N>#SmF-`|*viAywFvSiBZ_ zst>pt!MCo3uwJCSbrub zF_^D`^=I-(1`9Rv&I*H-HS*31gMJOHKa-Og44TmTGkFZd*&6fC3d3z`wIU0;Zp64MR+{kk#%uCK=Z|&wa4Js*m*8o z0(K~l|K7d@s){EDadW1DDQ2wP6OsSL6f@RlUqYN>uX*wOFeYJr zEj@|$_QltdFTR$1@wMcOuO(l6E%_guhD^TrTJpu$k}tlNeDSs9FFOI;zW7@5&zg=s z9$$Pd`JWw$cJ#&9k}tlNeDSs9i?1br_mj}FzW7@5#n+NAzLtFPwdC&sWmWns!Cdsk z*OD*3mVEKGUBo;pWqmD4CY4gq1AHxA%3LaCeJx2gmFf>!^#FAR^XatlwRArLJ_Nyr zpb*)+5I`GHIJwC3MY%rcCIaXB#SjJRgXjSf32i^DP0N{>y zCGW>x9|Jw7lFK5muYoRV4!fBhk*ma`La#shN?ZeY1DM2^8+*Hu7ySE9BtOlKy^+EI zJC{nD8+-d3LgWD9h;t*t1Nt*4ggmJMAYmP>Ic_daz6%cZ%o zcfaL>>f-YM#8DGuen ztTKLB?kkojEcaE5!*XAYS+D zFD*}4?pGFv<$i5(Snf9#n{vNUH%8@tr+P6g_5EH_ITbWF_I{A!P_C6dL8}hW%vm&03dRK;}UY#rt&5gazk{vv~^bO>p z$*0%55l>J3OvKYi)9t$9>1%mtZtV4w?BLm3e@z}5h~ksXA`i`tQLiClNNVaeT#Q!@ z&pwui=EnF6GqZ!|Fufxd+*KZV#x~*^qYprg;Tfl!GA#8PZ+U2LjIR?jJ9wt)i^)TC zV{f|Qfw^%N&5gYi4CX8d`KIbSBi+}MEAW3s$?|Qu) zAf2SSF%~o{05VCM8+$ACT>!bH`0%+=^N_EYAB`*a0ByCltxz58_$0OrPAMR>gP zd%RnFyy1Gh(aAc6da_F<_hM$7$sgXu+{FxWo#XNT^eb zVp&8b8ZV*}jTcdghKr~~&y$f$?#PM$tr_GPNenn2bBq&v4EM*xF60IOzMqr7Eiaix z6c=gp3HM`azAYl_jf7oO!Tr?!!(nuKfQiKd=}0D)<&=WKwyehz2T3gMWLO>~MkH{o zV}v>QoJg2Mj4+*;`%nr2VNTf@DJyyROq^=?Aqwclu0LzwITnFHL$KT3c3A>i2n}5{|EW+Bro{a9*C4i{>K{gKi-)CiH7`- z(jAiFe`*^BrS+dS{I{_7&yW}V8)%3r-^EI7Gz_N6-dq(iynR;0@Qz`qCd0eTStTblk+3(fy~0C-E&2!&gs53|}*e6Pv<1e#4w#*g_9Xm9LQWuZ9eN_QiEmi@y^L zN-h2ohKl%7B!>eNT+d|_8TAnYGL0s(5_V*MOjM}P5us#8OXSqo09qzXSgig45R(}V zcCuRl;xePbP*!34z?B&dRvMWK#f%q|~-bl>p2H3**>YfMil?QKRYs(vHVL z=&|#A?6B^yD8tMf>|Y)`fyb6|b4cz{;~tgfwjh+*f*NQtaO^mm+wO&MLHWJ*My$*S zel#DT&-y*-oJh3g_uY{}YRm6uT5Lu=B<;_fVA%T-GH?mw4{Olo{*XH&hT$_JhJ6eJ zeV6$on6se$F@NE2EzIiu!=%Bm&tJ>e4gA9e@~Mfh8~Eb|Vue)6Q%C;@1KGp0Kbp>w zjJy*bib|WvB*u4{KZ&Ij;{KZ}kWxz9fIi~H;Sj8ruN(Lq1>$vs%C&7k|BgUBA0aJb z-!(An)be!$|2+fYeGji2`0pEp$0NRO;BPW8Wu8a<4-7<~F2?;go{9whs4at{*pHdS zyl&usLIHDezo33cpeglIX`dm=PE&3;`z3>OK5mt9Kd+ir+BJ+{tzJPUS;P1>k_w;r zV|AJcTP_W=#i>Xw5Ac2m31fo+H(0-;nt=$F@e5Kr=T1Akj} z5ddB{U=MLmMc89Ydu#xYmGdY~1z$Jtw^MBqmV4xF2*^FM0^KXB1!VE2#kw~|wAum__R?S7GMHx0WXY2{$A=Oc!}hJkj!!4T#I!(pwFvhu)lacQhD z;66l#F#{upaTx}w{$RXepxtk91apF6>O?Zo?l+hw4Dx)dg5%GP7)}@#F`Q@^)}M#u zGnf+$SKLen+WiJH*~{y+km2%YBZh^SMGRLN2HO1wii88$IzAs+nwG8t(1 z8~kHBGF%$d?l*8uFT}A|743clWigx@)9x4EP)vGwHRk<1h*^v$X&SD=7{kQVukmVN z*J5lM7vsTS^amyj^B|!PU|5>Umqbp*OJocbh0Dc*R_a6;j#bg_H`vC~v~Zfz?l-Ux z>=cuBzd>so4>4)?8`uYU*!@<~?l-Ux@UVWWqTO#`AK+p4TSdFyp#4@ctK&gSwGbs6 zIXkK?k(`~ZoV5E5I*WLab2pWR@mke1UfeyB)2M3?iy^0|YfphTHns&dzbc?Y;L%ZML1dHLuns&dzi5A0; zHSKRO{mpjbloqU3_?0Cn z9u#Shf^lPb9#J2YQ+OVgR89r$eqm+8?BID(?S|Bb=cPtGFDRN@8lG1ajZO`Z*?w^< zX!jeuCfULBzM32HY-+^wp1LdI`A|)dcs{c7(C#<*Sh9oXd({Trwkhp?gC8QED%$-9 zKU$0p7&$xq$zs=OO1t0S7mMNRhjzcguNG^kigv%jZx&-`1$z2U?SYa^{r*s^Bf0*R zR8GY?%(6wq$@PY1$$ofrl$#~2N*Ko0Je6P62LY($sRSiG2EeQYgDO28AeN-vFU(3# z2k?{J{|##NSpY$jcE3RreLg@kNxR>mR$mN|lBesSsh$UrPSWl-DC@-l#U$;1gJya; zKuwZ&lc2d?0Z>lT?l)+mZw086hwz|I-vv-FYtf*kUIoxi)}lcx{V2eWvK9@t(N6;G zBv0f)yB zm@HJXd6P2Kn&!me&)^mRH~eb>JgZPxZe<|Yhtao2fhjst@ZR&`BkSgnQj-|Wx5e3Q>PQ9)ZE<#+I*P%{wm7>@9nGNM7H7Aq$qWYVcy^mQhT&{mp53OV zG2Est&TdneGMH<}v)j~V3|F_?G6&|F<~*==e*!!>PrcAHwta1qysIH_d}m)i5} zRyCu}+*p^SQ`ccU7Ln;ztX@Z6l^>^5FNBlZb!2lp&c8{5c4kKrBDV)%Zg?)<4geNZ@~mp8z^_ zlAG}3qL-%bL%`xvh_#c3Bc8#4nceD;t~ayrWGuszF*o}DNroq54IJ@g;fRNysH_kN zEd9w>!TUvHM?B;O|GtaK-`EjP=3kC@Kse&zi12_DBEm+Fct`}oXcEpou?1(4R*bz^LCu3V3@njl1;>rBW5lSGWwrKZ5l{YKj(GC_cEp4FFHqCLWXfHte1@f5 z>xidl9r3U@lzX3gj^+N#5l{YKj(GC_a>SG8rl8xv5f93}SJ4NmDR-5c9hGYx@f3M7 z21h(B4&}bAcEM(%DR-+Q9#igCM?9w7t&Vt1xeXlgpxl?#crclAUsu0HJm87zdc+v{ea%gF!($!s6s;p3X3x7&<1Jk}9Uktbtt#KY|1*;}_tfal+ic)&A64@8X7&v5NCEcLREc#1q3gCibh2hU;p zDDv6+5l@jPV{pVnI`o4JbRh=*aPWF7Hb1)xei8G|F9YXEe~I^wwwAXehZn7d5h1Q0J-M?7l)ypnaq!$TOq z#FH`iI{gAbP~yp$d%b=GAYHPKc-{ucl&mA3PXKZy>xgGFK(WM=F*xG+7NAt($rv2* z{0>l6vW|HE2B->F*yG%rct zyGwTjs4H1VJXnD_txDDrPfvjQl5~lCbw7YMC7z7I5f9ziw<}pkJbMCk;C28i%sW5K z{PDvZZonIztXrrjS+^*>EQoM$JAZf=^Iv6%>zaV~AAeH>c^e2gC;LC~+RtdJfKz3_ zc`M)~;%88Fz-hp*W{3kh;3)Ll5K0*wOg@io4dj>z*r5aVzJOh)$~xldfp8k;MVBJ6 zETXnL-jPL=*LV@-^)*W@$dQG45f9qrj_mb6h(V4uZ-7}~Jch-qw+nf}zi+b?_<1ts zjWi5cr150T+s{DHk@beRf5>0WlQHiA1LIDHCu5#0r+6|Z>oM;jiG{i;%!uA7!U%Kl zsz{han8byhcoX#I8)&q5$=4D86$>MNagtz8#=HgO1^-RkrbGUl z8}r}NnE%#>{5S56Tt*?c{}%Dz!6fkM&+6VuUhuD-i@!$x#~3Y3Xp#SM1JODn{}Top z`5(O8s8Z!JjEn@h)H-jR>Kf+Mt$(RS<$GD!$!pN!y2R$;4!oZ4QN9ISbLNx?TZ2@93qrt*zdw{siXmFym6M!o-npaf406dw|;7+MOK%ykItx|gdmZ5cYIZWBW%7!l1rxpI0m}T);442_eC6kETo?T(`Z9-TuklxYm=g?pbDKf> zK!dORfMLjw5ySA+5yL)nAOb9oJ3tX5m@|#9{Op1Qy=t5YZT-qmb>px6WO!1x^(#La zo|HBC%1;(w`56liBkzR2qtY5U=1NRrDQSG==gY9P$T3%S%fr*Q-2ppj3X^kyuYi-i|EH>Lt!Y#<20 zfBp{<|6ID_G5nVp{?5lB`K9DdEC1RZaJ*POa8EdgxQ?SkCg~LVk$;1Mu2W4HX8w%= z&0W!7J_5On{5SCo*zn)XBu?zcQ;_=>@`C^I`4PXJ=5bdP{-+xAKhu!^v3nx^XAfmi z^s~H}3pzDS;7CJp4MbMJFTY_vFke zKdELSAggUZWnW^&atWvWfm(zZ899DNjb>P?X`K2x#euUxQz6-N+Apgd_JZ?Y9*v95 z?90L#CqI!Lv4wqEIOXI|VI}G;PQqs?CM&q`F`XmfBXQ#A@PM&h<=1tk_0bQ0N&^qnP#Q+#4NvTrL?(87M|5#+2Hw*PL9 zzkj5Knn5Gb?+&oobL1Jvr*#|d$F9?gdSb^BlR`Q>Gl{der&oh?f~q0L*jI6UPX5b^w~nldc%{3fYz2bu<+-z7WhozSO6Jid8j7*9y7 zm#3FTJb@k;@g&U~!^Qej!IP5g;Ax_tLW-K#ln(ZVv)YC`r8`AVO@8??W z^wuXtH2ri>hDAI5&HK2;cPPyO$&FeK(~Cly;f*RaRIiR`_R(iVG$U-KdhkxUujJ0v z`iJR}Ukd&3Uf0X_KAT29#|7iUyKt@*L{$#xc zAS+89{}>Is2dAPWz4KU|0?5gRhJT#S0py!V`%cld0A>%vKVG*0C^cb=P1QRij4y9; z5fSiCAMkb@@SYj)7UjQ%!pvfwcNqWk2y*%kI4uU8ZUPQt-ve2|!4qD4iQ?OvW_Yky4xOnDFq?x9lMO?1z&(zysSH!fyNex@z-`a~ zar|~H?PrWvziSu@IE(lL2)VXQa?~(&sGQvpE((cgE;yM(acc^FQsvE3GIT

6Kg+zO^ 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 V$hv}jtojeDz~T3XfvRiD`7fa-ct!vK literal 0 HcmV?d00001 diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp new file mode 100644 index 0000000..8eb5659 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp @@ -0,0 +1,314 @@ +/* + * Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + */ +#include "steppin.h" +#include "stepper_controller.h" +#include "wiring_private.h" +#include "Arduino.h" + +extern StepperCtrl stepperCtrl; + +volatile int32_t stepsChanged=0; +volatile int64_t steps=0; + + +#if (PIN_STEP_INPUT != 0) +#error "this code only works with step pin being D0 (PA11, EXTINT11)" +#endif + + +#define WAIT_TCC2_SYNC() while(TCC2->SYNCBUSY.reg) + +void checkDir(void) +{ + int dir=1; + static int lastDir=-1; + + + if (CW_ROTATION == NVM->SystemParams.dirPinRotation) + { + dir=0; //reverse the rotation + } + + if (lastDir != dir) + { + if (dir) + { + EIC->CONFIG[1].reg &= ~EIC_CONFIG_SENSE2_Msk; + EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_HIGH; + + } else + { + EIC->CONFIG[1].reg &= ~EIC_CONFIG_SENSE2_Msk; + EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_LOW; + } + lastDir=dir; + } + +} + +//this function can not be called in interrupt context as the overflow interrupt for tC4 needs to run. +int64_t getSteps(void) +{ + +//#ifndef USE_NEW_STEP +// return 0; +//#endif + int64_t x; +#ifdef USE_TC_STEP + uint16_t y; + static uint16_t lasty=0; + + TCC2->CTRLBSET.reg=TCC_CTRLBSET_CMD_READSYNC; + WAIT_TCC2_SYNC(); + + + y=(uint16_t)(TCC2->COUNT.reg & 0x0FFFFul); //use only lowest 16bits + //LOG("count is %d",y); + steps += (int16_t)(y-lasty); + lasty=y; + + checkDir(); + return steps; + +#else + EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT11; + x=stepsChanged; + stepsChanged=0; + EIC->INTENSET.reg = EIC_INTENSET_EXTINT11; + return x; +#endif +} + + + + +//this function is called on the rising edge of a step from external device +static void stepInput(void) +{ + static int dir; + + //read our direction pin + dir = digitalRead(PIN_DIR_INPUT); + + if (CW_ROTATION == NVM->SystemParams.dirPinRotation) + { + dir=!dir; //reverse the rotation + } + +#ifndef USE_NEW_STEP + stepperCtrl.requestStep(dir,1); +#else + if (dir) + { + stepsChanged++; + }else + { + stepsChanged--; + } +#endif +} + +void enableEIC(void) +{ + PM->APBAMASK.reg |= PM_APBAMASK_EIC; + if (EIC->CTRL.bit.ENABLE == 0) + { + // Enable GCLK for IEC (External Interrupt Controller) + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC)); + + // Enable EIC + EIC->CTRL.bit.ENABLE = 1; + while (EIC->STATUS.bit.SYNCBUSY == 1) { } + } +} + + + + + +void setupStepEvent(void) +{ + //we will set up the EIC to generate an even on rising edge of step pin + //make sure EIC is setup + enableEIC(); + + + // Assign step pin to EIC + // Step pin is PA11, EXTINT11 + pinPeripheral(PIN_STEP_INPUT, PIO_EXTINT); + + //set up the direction pin PA10 to trigger external interrupt + pinPeripheral(PIN_DIR_INPUT, PIO_EXTINT); //EXTINT10 + + + //***** setup EIC ****** + EIC->EVCTRL.bit.EXTINTEO11=1; //enable event for EXTINT11 + EIC->EVCTRL.bit.EXTINTEO10=1; //enable event for EXTINT10 + //setup up external interurpt 11 to be rising edge triggered + //setup up external interurpt 10 to be both edge triggered + EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE3_RISE | EIC_CONFIG_SENSE2_HIGH; + + checkDir(); + + //disable actually generating an interrupt, we only want event triggered + EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT11; + EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT10; + + //**** setup the event system *** + // Enable GCLK for EVSYS channel 0 + PM->APBCMASK.reg |= PM_APBCMASK_EVSYS; + + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EVSYS_CHANNEL_0)); + while (GCLK->STATUS.bit.SYNCBUSY); + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EVSYS_CHANNEL_1)); + while (GCLK->STATUS.bit.SYNCBUSY); + + //setup the step pin to trigger event 0 on the TCC2 (step) + EVSYS->CHANNEL.reg=EVSYS_CHANNEL_CHANNEL(0) + | EVSYS_CHANNEL_EDGSEL_RISING_EDGE + | EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_11) + | EVSYS_CHANNEL_PATH_ASYNCHRONOUS; + + EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) + | EVSYS_USER_USER(EVSYS_ID_USER_TCC2_EV_0); + + //setup the dir pin to trigger event 2 on the TCC2 (dir change) + EVSYS->CHANNEL.reg=EVSYS_CHANNEL_CHANNEL(1) + | EVSYS_CHANNEL_EDGSEL_BOTH_EDGES + | EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_10) + | EVSYS_CHANNEL_PATH_ASYNCHRONOUS; + + EVSYS->USER.reg = EVSYS_USER_CHANNEL(2) + | EVSYS_USER_USER(EVSYS_ID_USER_TCC2_EV_1); + + //**** setup the Timer counter ****** + PM->APBCMASK.reg |= PM_APBCMASK_TCC2; + + // Enable GCLK for TCC2 (timer counter input clock) + GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TCC2_TC3)); + while (GCLK->STATUS.bit.SYNCBUSY); + + + + TCC2->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + WAIT_TCC2_SYNC(); + + TCC2->CTRLA.reg= TCC_CTRLA_SWRST; //reset TCC2 + WAIT_TCC2_SYNC(); + while(TCC2->CTRLA.bit.SWRST ==1); + + + //TCC2->WAVE.reg = TCC_WAVE_WAVEGEN_NFRQ; + //WAIT_TCC2_SYNC(); + + TCC2->EVCTRL.reg=TCC_EVCTRL_EVACT0_COUNTEV | TCC_EVCTRL_TCEI0 + | TCC_EVCTRL_EVACT1_DIR | TCC_EVCTRL_TCEI1; + WAIT_TCC2_SYNC(); + + + TCC2->COUNT.reg=0; + WAIT_TCC2_SYNC(); + + //TCC2->CTRLBSET.bit.CMD=TCC_CTRLBSET_CMD_RETRIGGER; + //checkDirPin(); + TCC2->CTRLBSET.bit.DIR=1; + + WAIT_TCC2_SYNC(); + TCC2->CTRLA.reg |=TCC_CTRLA_ENABLE; + WAIT_TCC2_SYNC(); + + + //checkDirPin(); + +// +// TC4->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 // Set Timer counter Mode to 16 bits +// | TC_CTRLA_WAVEGEN_NFRQ //normal counting mode (not using waveforms) +// | TC_CTRLA_PRESCALER_DIV1; //count each pulse +// WAIT_TC32_REGS_SYNC(TC4) +// +// TC4->COUNT16.CTRLBCLR.reg=0xFF; //clear all values. +// WAIT_TC32_REGS_SYNC(TC4) +// +// TC4->COUNT16.EVCTRL.reg=TC_EVCTRL_TCEI | TC_EVCTRL_EVACT_COUNT; //enable event input and count +// WAIT_TC32_REGS_SYNC(TC4) +// +// TC4->COUNT16.COUNT.reg=0; +// WAIT_TC32_REGS_SYNC(TC4) +// +// TC4->COUNT16.INTENSET.bit.OVF = 1; //enable over/under flow interrupt +// //setup the TC overflow/underflow interrupt +// NVIC_SetPriority(TC4_IRQn, 0); +// // Enable InterruptVector +// NVIC_EnableIRQ(TC4_IRQn); +// +// +// // Enable TC +// TC4->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; +// WAIT_TC32_REGS_SYNC(TC4) +} + +//static void dirChanged_ISR(void) +//{ +// int dir=0; +// //read our direction pin +// //dir = digitalRead(PIN_DIR_INPUT); +// if ( (PORT->Group[g_APinDescription[PIN_DIR_INPUT].ulPort].IN.reg & (1ul << g_APinDescription[PIN_DIR_INPUT].ulPin)) != 0 ) +// { +// dir=1; +// } +// +// +// if (CW_ROTATION == NVM->SystemParams.dirPinRotation) +// { +// dir=!dir; //reverse the rotation +// } +// if (dir) +// { +// TC4->COUNT16.CTRLBSET.bit.DIR=1; +// } else +// { +// TC4->COUNT16.CTRLBCLR.bit.DIR=1; +// } +//} + + +void stepPinSetup(void) +{ + + +#ifdef USE_TC_STEP + +// //setup the direction pin +// dirChanged_ISR(); +// +// //attachInterrupt configures the EIC as highest priority interrupts. +// attachInterrupt(digitalPinToInterrupt(PIN_DIR_INPUT), dirChanged_ISR, CHANGE); + setupStepEvent(); +// NVIC_SetPriority(EIC_IRQn, 1); //set port A interrupt as highest priority + + +#else + attachInterrupt(digitalPinToInterrupt(PIN_STEP_INPUT), stepInput, RISING); + NVIC_SetPriority(EIC_IRQn, 0); //set port A interrupt as highest priority +#endif + +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.h b/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.h new file mode 100644 index 0000000..62b13dd --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + */ +#ifndef __STEPPIN_H___ +#define __STEPPIN_H___ +#include "board.h" + +void stepPinSetup(void); //setup step pin + +int64_t getSteps(void); //returns the number of steps changed since last call + + +#endif // __STEPPIN_H___ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.cpp new file mode 100644 index 0000000..aaf270d --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.cpp @@ -0,0 +1,243 @@ +/* + * syslog.c + * + * Created on: Sep 14, 2011 + * Author: trampas.stern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ +#include "syslog.h" +#include +#include "board.h" + + +#define ANSI_WHITE "\033[37m" +#define ANSI_NORMAL "\033[0m" +#define ANSI_BLINK "\033[5m" +#define ANSI_BLUE "\033[34m" +#define ANSI_MAGENTA "\033[35m" +#define ANSI_CYAN "\033[36m" +#define ANSI_WHITE "\033[37m" +#define ANSI_RED "\033[31m" +#define ANSI_GREEN "\033[32m" +#define ANSI_PINK "\033[35m\033[1m" +#define ANSI_BROWN "\033[33m" +#define ANSI_YELLOW "\033[33m\033[1m" +#define ANSI_BLACK "\033[30m" +#define ANSI_BELL_AND_RED "\a\033[31m" + +#define NEW_LINE "\n\r" + +Stream *ptrSerial=NULL; +eLogLevel SyslogLevelToWrite; + +bool DebugUART=false; +static char buffer[SYSLOG_BUFFER_SIZE]; +static unsigned int BufIndex=0; + +static int SysLog_Enabled=1; + +int SysLogDisable(void) +{ + SysLog_Enabled=0; + return 0; +} + +int SysLogEnable(void) +{ + SysLog_Enabled=1; + return 0; +} + +int SysLogIsEnabled(void) +{ + return SysLog_Enabled; +} +void SysLogDebug(bool x) +{ + DebugUART=x; +} + +void SysLogPuts(const char *ptrStr) +{ + if (!SysLog_Enabled) + return; + + if (NULL == ptrSerial) + { + while(*ptrStr) + { + + SYSLOG_PUTC(*ptrStr); + ptrStr++; + } + } else + { + ptrSerial->write(ptrStr); + } +#ifndef MECHADUINO_HARDWARE + if (DebugUART) + { + SerialUSB.write(ptrStr); + } +#endif +} + +int SysLogInitDone=0; +void SysLogInit(Stream *ptrSerialObj, eLogLevel LevelToWrite) +{ + ptrSerial=ptrSerialObj; + SyslogLevelToWrite=LevelToWrite; + + SysLogInitDone=1; + BufIndex=0; + memset(buffer,0,SYSLOG_BUFFER_SIZE); +} + + +int SysLogProcessing=0; // this is used such that syslog can be reentrent +int SysLogMissed=0; + + +void SysLog(eLogLevel priorty, const char *fmt, ...) +{ + //UINT32 ret; + int previousState=SysLog_Enabled; + char vastr[MAX_SYSLOG_STRING]={0}; + //char outstr[MAX_SYSLOG_STRING]={0}; + + + va_list ap; + + if (SysLogProcessing) + { + //we have a syslog from a syslog call thus return as not much we can do... + //memset(buffer,0,SYSLOG_BUFFER_SIZE); + va_start(ap,fmt); + vsnprintf(&buffer[BufIndex],SYSLOG_BUFFER_SIZE-BufIndex,(char *)fmt,ap); + BufIndex=strlen(buffer); + snprintf(&buffer[BufIndex],SYSLOG_BUFFER_SIZE-BufIndex,NEW_LINE); + BufIndex=strlen(buffer); + SysLogMissed++; //set flag that we missed a call + return; + } + + SysLogProcessing=1; + + //stop the watch dog will doing a SysLog print + Sys_WDogHoldOn(); + + if(!SysLogInitDone) + { + SysLogInit(NULL, LOG_WARNING); //not sure who is reseting serial port but before we print set it up + WARNING("You should init SysLog"); + //SysLogInitDone=0; + } + + //Send out a * that we missed a SysLog Message before this current message + if (SysLogMissed) + { + //SysLogPuts(ANSI_RED); + SysLogPuts("*** Reentrant Log call possible loss of message(s):"); + SysLogPuts(NEW_LINE); + if (BufIndex>0) + { + SysLogPuts(buffer); + memset(buffer,0,SYSLOG_BUFFER_SIZE); + BufIndex=0; + } + //SysLogPuts(ANSI_RED); + SysLogPuts("***********"); + SysLogPuts(NEW_LINE); + SysLogMissed=0; + } + memset(vastr,0,MAX_SYSLOG_STRING); + va_start(ap,fmt); +//#ifndef PGM_P +#if 1 + vsnprintf(vastr,MAX_SYSLOG_STRING,(char *)fmt,ap); +#else + vsprintf_P(vastr,(const char *)fmt,ap); +#endif + //get time and store in datetimestr if desired + //sprintf(outstr, "[%s] %s\r\n", datetimestr, vastr); + + + + if (priorty<=LOG_ERROR) + { + SysLog_Enabled=1; + SysLogPuts(ANSI_RED); + + }else if (priorty==LOG_DEBUG) + { + SysLogPuts(ANSI_WHITE); + }else if (priorty==LOG_WARNING) + { + SysLogPuts(ANSI_BLUE); + } + +#ifdef RTC_H_ +#ifdef TIME_H_ + { + struct tm tp; + RTC_Time_s tm; + time_t secs; + char datetimestr[MAX_SYSLOG_STRING]={0}; + + RTC_ReadTime(&tm); + secs=tm.seconds; + convertFlexNetTime((time_t *)&secs, &tp); + time_str(datetimestr,&tp); + SysLogPuts(datetimestr); + + if (priorty<=SyslogLevelToWrite && SysLogWriteFunc!=NULL) + { + SysLogWriteFunc(datetimestr,strlen(datetimestr)); + } + } +#endif +#endif + + SysLogPuts(vastr); +// +// if (priorty<=SyslogLevelToWrite && SysLogWriteFunc!=NULL) +// { +// SysLogWriteFunc(vastr,strlen(vastr)); +// SysLogWriteFunc(NEW_LINE,strlen(NEW_LINE)); +// } + + + SysLogPuts(ANSI_NORMAL); + SysLogPuts(NEW_LINE); + + + + if (priorty == LOG_EMERG) { + //you can reboot processor here + } + + //start the watch dog where left off.. + Sys_WDogHoldOff(); + SysLogProcessing=0; + SysLog_Enabled=previousState; + return; +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.h b/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.h new file mode 100644 index 0000000..acd7b2e --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.h @@ -0,0 +1,210 @@ +/* + * syslog.h + * + * Created on: Sep 14, 2011 + * Author: trampas.stern + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#ifndef SYSLOG_H_ +#define SYSLOG_H_ + +#include +#include +#include +#include "Arduino.h" +#include "variant.h" + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +#define SYSLOG_BUFFER_SIZE (250) + +#define MAX_SYSLOG_STRING (250) +#define __FILENAME1__ (__builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__) +#define __FILENAME__ (__builtin_strrchr(__FILENAME1__, '/') ? __builtin_strrchr(__FILENAME1__, '/') + 1 : __FILENAME1__) + +#define SYSLOG_WRITE(buffer,nBytes) + +#ifdef CMD_SERIAL_PORT +#define SYSLOG_PUTC(x) +#else +#define SYSLOG_PUTC(x) //SerialUSB.write(x) +#endif + +#define Sys_WDogHoldOn() +#define Sys_WDogHoldOff() +/* + * priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). Both the priorities and the facilities map roughly + * one-to-one to strings in the syslogd(8) source code. This mapping is + * included in this file. + * + * priorities (these are ordered) + */ + +typedef enum _eLogLevel { + LOG_EMERG = 0, // system is unusable + LOG_ALERT = 1, // action must be taken immediately + LOG_CRIT = 2, // critical conditions + LOG_ERROR = 3, // error conditions + LOG_WARNING = 4, // warning conditions + LOG_NOTICE = 5, // normal but significant condition + LOG_INFO = 6, // informational + LOG_DEBUG = 7, // debug-level messages + LOG_DISABLED = 8 // disabled messages +} eLogLevel; + +#if 0 +#define CONCAT(x, y) CONCAT_(x, y) +#define CONCAT_(x, y) x##y + +#define ID(...) __VA_ARGS__ + +#define IFMULTIARG(if,then,else) \ +CONCAT(IFMULTIARG_, IFMULTIARG_(if, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ +1, 1, 0, ))(then,else) +#define IFMULTIARG_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, \ +_10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ +_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ +_30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ +_40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \ +_50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \ +_60, _61, _62, _63, ...) _63 +#define IFMULTIARG_0(then, else) else +#define IFMULTIARG_1(then, else) then + +#define PROVIDE_SECOND_ARGUMENT(x, ...) CONCAT( IFMULTIARG(ID(__VA_ARGS__), INSERT_, ADD_), SECOND_ARGUMENT ) (x, __VA_ARGS__) +#define PROVIDE_SECOND_ARGUMENT2(x, y, ...) CONCAT( IFMULTIARG(ID(__VA_ARGS__), INSERT_, ADD_), SECOND_ARGUMENT2 ) (x, y, __VA_ARGS__) + +#define ADD_SECOND_ARGUMENT(x, y) y, x +#define INSERT_SECOND_ARGUMENT(x, y, ...) y, x, __VA_ARGS__ + +#define ADD_SECOND_ARGUMENT2(x, z, y) y, x, z +#define INSERT_SECOND_ARGUMENT2(x, z, y, ...) y, x, z, __VA_ARGS__ + +#endif +//#define DEBUG1(...) printf( "DEBUG %s %s: " +//PROVIDE_SECOND_ARGUMENT2(__FILE__, __LINE__, __VA_ARGS__)) + + +//TXT(x) macro is used for system which can store strings in flash, like AVR processors +#ifndef TXT + #define TXT(x) x +#endif + +void SysLog(eLogLevel priorty, const char *fmt, ...); + + + +static inline const char * __file__( const char *filename ) { + char const *p = strrchr( filename, '/' ); + if ( p ) + return p+1; + else + return filename; +} // __file__ + + +//These macros abstract the logging and append the file and line number to errors. +#ifndef SYSLOG_DISABLE +//#ifndef PGM_P +#if 1 +//EMERG means system is unstable thus will force a reboot! +#define EMERG(fmt, ...) SysLog( LOG_EMERG, "EMERG: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) +#define ALERT(fmt, ...) SysLog( LOG_ALERT, "ALERT: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) +#define CRITICAL(fmt, ...) SysLog( LOG_CRIT, "CRITICAL: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) +#define ERROR(fmt, ...) SysLog( LOG_ERROR, "ERROR: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) +#define WARNING(fmt, ...) SysLog( LOG_WARNING, "WARNING: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) +#define NOTICE(fmt, ...) SysLog( LOG_NOTICE, "NOTICE: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) +#define INFO(fmt, ...) SysLog( LOG_INFO, "INFO: %s %4d: " fmt, __FILENAME__, __LINE__, ## __VA_ARGS__ ) +#define LOG(fmt, ...) SysLog( LOG_DEBUG, "%s %4d: " fmt, __FILENAME__ , __LINE__, ## __VA_ARGS__ ) +// +//#define EMERG(...) SysLog( LOG_EMERG, "EMERG: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +//#define ALERT(...) SysLog( LOG_ALERT, "ALERT: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +//#define CRITICAL(...) SysLog( LOG_CRIT, "CRITICAL: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +//#define ERROR(...) SysLog( LOG_ERROR, "ERROR: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +//#define WARNING(...) SysLog( LOG_WARNING, "WARNING: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +//#define NOTICE(...) SysLog( LOG_NOTICE, "NOTICE: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +//#define INFO(...) SysLog( LOG_INFO, "INFO: %15s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +//#define LOG(...) SysLog( LOG_DEBUG, "%s %4d: " PROVIDE_SECOND_ARGUMENT2(BASE_FILE_NAME, __LINE__,__VA_ARGS__ ) ) +#else +//EMERG means system is unstable thus will force a reboot! +#define EMERG(fmt, ...) SysLog( LOG_EMERG, PSTR("EMERG: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) +#define ALERT(fmt, ...) SysLog( LOG_ALERT, PSTR("ALERT: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) +#define CRITICAL(fmt, ...) SysLog( LOG_CRIT, PSTR("CRITICAL: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) +#define ERROR(fmt, ...) SysLog( LOG_ERROR, PSTR("ERROR: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) +#define WARNING(fmt, ...) SysLog( LOG_WARNING, PSTR("WARNING: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) +#define NOTICE(fmt, ...) SysLog( LOG_NOTICE, PSTR("NOTICE: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) +#define INFO(fmt, ...) SysLog( LOG_INFO, PSTR("INFO: %15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) +#define LOG(fmt, ...) SysLog( LOG_DEBUG, PSTR("%15s %4d: " fmt), __file__(__FILE__), __LINE__, ## __VA_ARGS__ ) + +#endif +#else +#define EMERG(fmt, ...) +#define ALERT(fmt, ...) +#define CRITICAL(fmt, ...) +#define ERROR(fmt, ...) +#define WARNING(fmt, ...) +#define NOTICE(fmt, ...) +#define INFO(fmt, ...) +#define LOG(fmt, ...) + +#endif //SYSLOG_DIABLE + +//Note that if you are running debug code with JTAG the assert will stop +// However you might want to run release code with syslog enabled for testing +// where you want error logging, but asserts are not enabled. +// Thus this macro does error logging and an assert. +//This macro assumed to take a constant string as argument + + +//this can be enabled to log asserts to the history file, if you have code space to do it. +#ifdef ASSERT_HISTORY +#define ASSERT(x) {if(!(x)){ERROR(#x); HISTORY_ASSERT();} assert(x);} +#define ASSERT_ERROR(x) {HISTORY_ASSERT(); ERROR(x); ASSERT_FAIL(x);} +#else +#define ASSERT(x) {if(!(x)){ERROR(#x);} assert(x);} +#define ASSERT_ERROR(x) {ERROR(x); ASSERT_FAIL(x);} +#endif + + +void SysLogInit(Stream *ptrSerialObj, eLogLevel LevelToWrite); +int SysLogDisable(void); +int SysLogEnable(void); +int SysLogIsEnabled(void); + +void SysLogDebug(bool x); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif /* SYSLOG_H_ */ diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/utils.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/utils.cpp new file mode 100644 index 0000000..144ec2e --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/utils.cpp @@ -0,0 +1,45 @@ +/********************************************************************** + * Author: tstern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +#include "utils.h" +#include "syslog.h" + +double CubicInterpolate( + double y0,double y1, + double y2,double y3, + double mu) +{ + double a0,a1,a2,a3,mu2; + + mu2 = mu*mu; + a0 = y3 - y2 - y0 + y1; + a1 = y0 - y1 - a0; + a2 = y2 - y0; + a3 = y1; + + return(a0*mu*mu2+a1*mu2+a2*mu+a3); +} + + + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/utils.h b/firmware_smartstepper_trikarus/stepper_nano_zero/utils.h new file mode 100644 index 0000000..b8f1a11 --- /dev/null +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/utils.h @@ -0,0 +1,39 @@ +/********************************************************************** + * Author: tstern + * + Copyright (C) 2018 MisfitTech, All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Written by Trampas Stern for MisfitTech. + + Misfit Tech invests time and resources providing this open source code, + please support MisfitTech and open-source hardware by purchasing + products from MisfitTech, www.misifittech.net! + *********************************************************************/ + +/* this file contains generic utilities and functions */ + +#ifndef UTILS_H_ +#define UTILS_H_ + + +double CubicInterpolate( + double y0,double y1, + double y2,double y3, + double mu); + + + + +#endif /* UTILS_H_ */ diff --git a/grafana/collectd_InfluxDB Metrics.json b/grafana/collectd_InfluxDB Metrics.json new file mode 100644 index 0000000..5bac6bc --- /dev/null +++ b/grafana/collectd_InfluxDB Metrics.json @@ -0,0 +1,14085 @@ +{ + "__inputs": [ + { + "name": "DS_INFLUXDB_| COLLECTD", + "label": "InfluxDB | collectd", + "description": "", + "type": "datasource", + "pluginId": "influxdb", + "pluginName": "InfluxDB" + }, + { + "name": "DS_INFLUXDB_| TRIKARUS", + "label": "InfluxDB | trikarus", + "description": "", + "type": "datasource", + "pluginId": "influxdb", + "pluginName": "InfluxDB" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.0.6" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "influxdb", + "name": "InfluxDB", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:353", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "This dashboard provides various performance metrics for Linux systems, with templating to select the influxdb datasource and host.", + "editable": true, + "gnetId": 6642, + "graphTooltip": 1, + "id": null, + "links": [], + "panels": [ + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 122, + "panels": [ + { + "cacheTimeout": null, + "content": "

\n\n
", + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 23, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 39, + "links": [], + "mode": "html", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "1m" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "interface_tx", + "orderByTime": "ASC", + "policy": "default", + "query": "", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "/60" + ], + "type": "math" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$hostname$/" + }, + { + "condition": "AND", + "key": "instance", + "operator": "=~", + "value": "/^$ifname$/" + }, + { + "condition": "AND", + "key": "type", + "operator": "=", + "value": "if_octets" + } + ] + } + ], + "title": "Webcam", + "type": "text" + } + ], + "title": "Webcam Logitech C920", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 31, + "panels": [], + "title": "Last One Hour Realtime Statistics", + "type": "row" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "$$hashKey": "object:154", + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + }, + { + "$$hashKey": "object:155", + "id": 1, + "op": "=", + "text": "(I) Idle", + "type": 1, + "value": "0" + }, + { + "$$hashKey": "object:156", + "id": 2, + "op": "=", + "text": "(P) Printing from SD Card", + "type": 1, + "value": "1" + }, + { + "$$hashKey": "object:157", + "id": 3, + "op": "=", + "text": "(S) Stopped", + "type": 1, + "value": "2" + }, + { + "$$hashKey": "object:158", + "id": 4, + "op": "=", + "text": "(C) Running config file", + "type": 1, + "value": "3" + }, + { + "$$hashKey": "object:159", + "id": 5, + "op": "=", + "text": "(A) Paused", + "type": 1, + "value": "4" + }, + { + "$$hashKey": "object:160", + "id": 6, + "op": "=", + "text": "(D) Pausing", + "type": 1, + "value": "5" + }, + { + "$$hashKey": "object:161", + "id": 7, + "op": "=", + "text": "(R) Resuming from pause", + "type": 1, + "value": "6" + }, + { + "$$hashKey": "object:162", + "id": 8, + "op": "=", + "text": "(B) Busy", + "type": 1, + "value": "7" + }, + { + "$$hashKey": "object:163", + "id": 9, + "op": "=", + "text": "(F) Firmware Update", + "type": 1, + "value": "8" + }, + { + "$$hashKey": "object:164", + "id": 10, + "op": "=", + "text": "(O) Offline / no PSU voltage", + "type": 1, + "value": "-1" + }, + { + "$$hashKey": "object:176", + "id": 11, + "op": "=", + "text": "No network", + "type": 1, + "value": "-2" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "#F2495C", + "value": -1 + }, + { + "color": "#299c46", + "value": 0 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 0, + "y": 2 + }, + "id": 70, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(status) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Controller Status", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "On", + "type": 1, + "value": "0" + }, + { + "id": 1, + "op": "=", + "text": "Off", + "type": 1, + "value": "1" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "purple", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "purple", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 5, + "y": 2 + }, + "id": 83, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(value) from \"relay_states_value\" WHERE \"type_instance\" = 'pin_psu' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de'", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "PSU Status", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "Off", + "type": 1, + "value": "0" + }, + { + "id": 1, + "op": "=", + "text": "On", + "type": 1, + "value": "1" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "yellow", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "#EAB839", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 10, + "y": 2 + }, + "id": 82, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(value) from \"relay_states_value\" WHERE \"type_instance\" = 'pin_ledspot' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de'", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "LED Status", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "description": "0.0 V cannot be displayed because the controller just would be offline\n0.1 V to 5.0 V is USB only voltage\n22.0 V is shutdown voltage\n23.0 V is resume voltage\n24.0 V to 24.3 V is regular voltage from power supply", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 1, + "mappings": [ + { + "$$hashKey": "object:224", + "id": 0, + "op": "=", + "text": "n.a.", + "type": 1, + "value": "99999" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "yellow", + "value": 0.5 + }, + { + "color": "#EAB839", + "value": 5 + }, + { + "color": "red", + "value": 22 + }, + { + "color": "red", + "value": 23 + }, + { + "color": "green", + "value": 24 + }, + { + "color": "green", + "value": 24.3 + }, + { + "color": "red", + "value": 24.4 + } + ] + }, + "unit": "volt" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 15, + "y": 2 + }, + "id": 84, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(vin) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "PSU Voltage @ Duet", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 1, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(0, 0, 0)", + "value": null + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 2 + }, + "hideTimeOverride": true, + "id": 1, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "expr": "", + "groupBy": [], + "intervalFactor": 2, + "measurement": "system", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(\"value\") FROM \"uptime_value\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de'", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "uptime" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": "1h", + "title": "RPi Uptime", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 102400000 + }, + { + "color": "rgba(50, 172, 45, 0.97)", + "value": 204800000 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 0, + "y": 6 + }, + "hideTimeOverride": true, + "id": 4, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "mean" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "10s" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "mem", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"memory_value\" WHERE \"type_instance\" = 'free' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time(10s) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "available_percent" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": "1h", + "title": "Free Memory", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 5, + "y": 6 + }, + "hideTimeOverride": true, + "id": 21, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"memory_value\" WHERE \"type_instance\" = 'cached' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time(10s) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": "1h", + "title": "Memory Cached", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 10, + "y": 6 + }, + "hideTimeOverride": true, + "id": 3, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "expr": "", + "groupBy": [], + "intervalFactor": 2, + "measurement": "mem", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"memory_value\" WHERE \"type_instance\" = 'used' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time(10s) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": "1h", + "title": "Memory Used", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 5, + "x": 15, + "y": 6 + }, + "hideTimeOverride": true, + "id": 20, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"memory_value\" WHERE \"type_instance\" = 'buffered' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time(10s) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": "1h", + "title": "Memory Buffered", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 10 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 5 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 6 + }, + "hideTimeOverride": true, + "id": 2, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "expr": "", + "groupBy": [], + "intervalFactor": 2, + "measurement": "system", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"load_midterm\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time(10s) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "n_cpus" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": "1h", + "title": "5min Load", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 3, + "mappings": [ + { + "$$hashKey": "object:368", + "id": 0, + "op": "=", + "text": "n.a.", + "type": 1, + "value": "99999" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(0, 0, 0)", + "value": null + } + ] + }, + "unit": "lengthmm" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 0, + "y": 10 + }, + "id": 86, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(z_coord) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Z Coord", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 3, + "mappings": [ + { + "$$hashKey": "object:416", + "id": 0, + "op": "=", + "text": "n.a.", + "type": 1, + "value": "99999" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(0, 0, 0)", + "value": null + } + ] + }, + "unit": "lengthmm" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 3, + "y": 10 + }, + "id": 77, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(babystep) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Z Baby Step", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 1, + "mappings": [ + { + "$$hashKey": "object:464", + "id": 0, + "op": "=", + "text": "n.a.", + "type": 1, + "value": "99999" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 6, + "y": 10 + }, + "id": 76, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(mcu_temp) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Duet MCU Temperature", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 1, + "mappings": [ + { + "$$hashKey": "object:512", + "id": 0, + "op": "=", + "text": "n.a.", + "type": 1, + "value": "99999" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": 170 + }, + { + "color": "green", + "value": 240 + }, + { + "color": "#EAB839", + "value": 250 + }, + { + "color": "dark-yellow", + "value": 260 + }, + { + "color": "red", + "value": 275 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 9, + "y": 10 + }, + "id": 78, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(hotend_temp) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "SuperVolcano Hotend Temperature", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 1, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 80 + }, + { + "color": "red", + "value": 85 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 12, + "y": 10 + }, + "hideTimeOverride": true, + "id": 45, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "expr": "", + "groupBy": [], + "intervalFactor": 2, + "measurement": "system", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(\"value\") FROM \"cpu_temp_value\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de'", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "uptime" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "timeFrom": "1h", + "title": "RPi CPU Temperature", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 1, + "mappings": [ + { + "$$hashKey": "object:272", + "id": 0, + "op": "=", + "text": "n.a.", + "type": 1, + "value": "99999" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "green", + "value": 25 + }, + { + "color": "green", + "value": 100 + }, + { + "color": "red", + "value": 125 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 15, + "y": 10 + }, + "id": 79, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(extrfactor) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Extrusion Factor", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 1, + "mappings": [ + { + "$$hashKey": "object:320", + "id": 0, + "op": "=", + "text": "n.a.", + "type": 1, + "value": "99999" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 200 + }, + { + "color": "red", + "value": 300 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 18, + "y": 10 + }, + "id": 80, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "sum" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "alias": "", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(speedfactor) FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "table", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Speed Factor", + "type": "stat" + }, + { + "cacheTimeout": null, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "fieldConfig": { + "defaults": { + "custom": {}, + "decimals": 0, + "mappings": [ + { + "id": 0, + "op": "=", + "text": "N/A", + "type": 1, + "value": "null" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "purple", + "value": null + }, + { + "color": "purple", + "value": 1 + }, + { + "color": "red", + "value": 2 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 3, + "x": 21, + "y": 10 + }, + "hideTimeOverride": true, + "id": 22, + "interval": null, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "lastNotNull" + ] + }, + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "mean" + ], + "fields": "", + "values": false + } + }, + "pluginVersion": "7.0.6", + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"users_value\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": "1h", + "title": "RPi Users/Sessions", + "type": "stat" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 58, + "panels": [], + "title": "All-over Network", + "type": "row" + }, + { + "aliasColors": {}, + "bars": true, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 15 + }, + "hiddenSeries": false, + "id": 43, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": false, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "received", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "1h" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "interface_rx", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT non_negative_derivative(mean(\"value\"), 1h) FROM \"interface_rx\" WHERE (\"host\" = 'hangprinter-pi.fablabchemnitz.de' AND \"type\" = 'if_octets') AND $timeFilter GROUP BY time(1h) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "1h" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + }, + { + "condition": "AND", + "key": "type", + "operator": "=", + "value": "if_octets" + } + ] + }, + { + "alias": "sent", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "1h" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "interface_tx", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT non_negative_derivative(mean(\"value\"), 1h) FROM \"interface_tx\" WHERE (\"host\" = 'hangprinter-pi.fablabchemnitz.de' AND \"type\" = 'if_octets') AND $timeFilter GROUP BY time(1h) fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "1h" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + }, + { + "condition": "AND", + "key": "type", + "operator": "=", + "value": "if_octets" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Utilization (Hourly)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 15 + }, + "hiddenSeries": false, + "id": 23, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "$tag_instance Errors In", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT derivative(mean(value), 1s) FROM \"interface_rx\" WHERE \"type\"='if_errors' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval), instance fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "$tag_instance Errors Out", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT derivative(mean(value), 1s) FROM \"interface_tx\" WHERE \"type\"='if_errors' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval), instance fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_sent" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Errors", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 15 + }, + "hiddenSeries": false, + "id": 14, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "$tag_instance Data In", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT derivative(mean(value), 1s)*8 FROM \"interface_rx\" WHERE \"type\"='if_octets' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval), instance fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "$tag_instance Data Out", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT derivative(mean(value), 1s)*8 FROM \"interface_tx\" WHERE \"type\"='if_octets' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval), instance fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_sent" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Network Traffic", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0.9 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "E", + "10s", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "0", + "frequency": "10s", + "handler": 1, + "message": "Duet could not be pinged. Maybe controller was reset by M112, M999 or reconfigured by M552", + "name": "Duet 2 pings @ local alert", + "noDataState": "keep_state", + "notifications": [ + { + "uid": "ye2notZgk" + } + ] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": 2, + "description": "drop rate of 1.0 means there is no connection at all! The information is helpful to see if device was rebooted for example.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 22 + }, + "hiddenSeries": false, + "id": 62, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "latency (ms)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"ping_value\" WHERE type = 'ping' AND host = 'hangprinter-pi.fablabchemnitz.de' AND type_instance = 'yourduet' AND $timeFilter GROUP BY type_instance , time($__interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "standard devation (ms)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"ping_value\" WHERE type = 'ping_stddev' AND host = 'hangprinter-pi.fablabchemnitz.de' AND type_instance = 'yourduet' AND $timeFilter GROUP BY type_instance , time($__interval) fill(null)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "drop rate", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"ping_value\" WHERE type = 'ping_droprate' AND host = 'hangprinter-pi.fablabchemnitz.de' AND type_instance = 'yourduet' AND $timeFilter GROUP BY type_instance , time($__interval) fill(null)", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.9 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Duet 2 pings @ local (data from hangprinter-pi)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:730", + "decimals": 2, + "format": "none", + "label": null, + "logBase": 1, + "max": "1", + "min": 0, + "show": true + }, + { + "$$hashKey": "object:731", + "decimals": 2, + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0.9 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "E", + "1m", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "0m", + "frequency": "10s", + "handler": 1, + "name": "c-MaschinenBoom-FLC pings @ local alert", + "noDataState": "keep_state", + "notifications": [ + { + "uid": "ye2notZgk" + } + ] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": 2, + "description": "drop rate of 1.0 means there is no connection at all! The information is helpful to see if device was rebooted for example.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 63, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "sideWidth": null, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "latency (ms)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"ping_value\" WHERE type = 'ping' AND host = 'hangprinter-pi.fablabchemnitz.de' AND type_instance = '2001:bc8:3f13:ffc2:ee08:6bff:feb8:1778' AND $timeFilter GROUP BY type_instance , time($__interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "standard devation (ms)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"ping_value\" WHERE type = 'ping_stddev' AND host = 'hangprinter-pi.fablabchemnitz.de' AND type_instance = '2001:bc8:3f13:ffc2:ee08:6bff:feb8:1778' AND $timeFilter GROUP BY type_instance , time($__interval) fill(null)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "drop rate", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "net", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"ping_value\" WHERE type = 'ping_droprate' AND host = 'hangprinter-pi.fablabchemnitz.de' AND type_instance = '2001:bc8:3f13:ffc2:ee08:6bff:feb8:1778' AND $timeFilter GROUP BY type_instance , time($__interval) fill(null)", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "bytes_recv" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.9 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "c-MaschinenBoom-FLC pings @ local (data from hangprinter-pi)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:682", + "decimals": 2, + "format": "none", + "label": null, + "logBase": 1, + "max": "150", + "min": 0, + "show": true + }, + { + "$$hashKey": "object:683", + "decimals": 2, + "format": "ms", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 124, + "panels": [], + "title": "Duet 2 Ethernet v1.04", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 1, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 35 + }, + "hiddenSeries": false, + "id": 125, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Temperature", + "color": "#F2495C" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Temperature", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"hotend_temp\") FROM \"duet_ethernet\" WHERE $timeFilter GROUP BY time(60s)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "SuperVolcano Hotend Temperatures", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "celsius", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 1, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 35 + }, + "hiddenSeries": false, + "id": 126, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:230", + "alias": "Temperature", + "color": "#FF9830" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Temperature", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"mcu_temp\") FROM \"duet_ethernet\" WHERE $timeFilter GROUP BY time(60s)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "MCU Temperature", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:243", + "decimals": 1, + "format": "celsius", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:244", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 24 + ], + "type": "lt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "10s", + "now" + ] + }, + "reducer": { + "params": [], + "type": "last" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "0m", + "frequency": "3s", + "handler": 1, + "message": "Duet VIN Power dropped below 24.0 V", + "name": "Duet 2 Voltage (VIN) alert", + "noDataState": "keep_state", + "notifications": [ + { + "uid": "ye2notZgk" + } + ] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 1, + "description": "This normally should be 24.0 to 24.3 V. If it is 5 V or below it points to \n- powering the Duet by Raspberry Pi now (which gets the power from UPS)\n- 230 V supply was shut down completely (emergency button was hit or regular shut down of main power cord)\n- possible problem with wiring.\n\nTo check against please also have a look at Smart Stepper monitoring. They can only be online if they are powered by USB 5 V and/or 24 V main power.\n\nThe voltage cannot be 0 V because Duet would be just offline and could not deliver those measurement values", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 35 + }, + "hiddenSeries": false, + "id": 85, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Voltage", + "color": "#FF9830" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Voltage", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"vin\") FROM \"duet_ethernet\" WHERE $timeFilter GROUP BY time(60s)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "lt", + "value": 24 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Voltage (VIN)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 1, + "format": "volt", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "id": 128, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Extrusion Factor", + "color": "#5794F2" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Extrusion Factor", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"extrfactor\" FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Extrusion Factor History", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 43 + }, + "hiddenSeries": false, + "id": 129, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Print Speed Factor", + "color": "#B877D9" + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Print Speed Factor", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"speedfactor\" FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Print Speed Factor History", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "percent", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 1, + "description": "-2 = No network connection\n-1 = O = Offline / no PSU voltage\n 0 = I = idle\n 1 = P = printing from SD card (processing)\n 2 = S = paused (i.e. needs a reset)\n 3 = C = running config file (i.e starting up)\n 4 = A = paused\n 5 = D = pausing\n 6 = R = resuming from a pause\n 7 = B = busy (e.g. running a macro)\n 8 = F = performing firmware update\n 9 = T = changing tool\n 10 = S = simulating\n 11 = H = halted", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 43 + }, + "hiddenSeries": false, + "id": 81, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Status", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"status\" FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Controller Status Transition History", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:468", + "decimals": 0, + "format": "none", + "label": null, + "logBase": 1, + "max": "8", + "min": "-1", + "show": true + }, + { + "$$hashKey": "object:469", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 3, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 10, + "gridPos": { + "h": 8, + "w": 16, + "x": 0, + "y": 51 + }, + "hiddenSeries": false, + "id": 87, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Z Coord", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"z_coord\" FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Z Coord History", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:963", + "decimals": 3, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": "2500", + "min": "-10", + "show": true + }, + { + "$$hashKey": "object:964", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 51 + }, + "hiddenSeries": false, + "id": 72, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Baby Step", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT \"babystep\" FROM \"duet_ethernet\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Baby Steps History", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 59 + }, + "id": 66, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The average speed is calculated in 5 second interval by script. Have a look at rotaryEncoder.py file", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 60 + }, + "hiddenSeries": false, + "id": 64, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Current speed (mm/s)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mm_per_s FROM \"rotary_encoder\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Onrush (mm/s)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT gust FROM \"rotary_encoder\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "F", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Average speed (mm/s)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT avg FROM \"rotary_encoder\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "G", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Velocities", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1920", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1921", + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The travel distance is a kind of absolute sum which is added/subtracted by rough value 3.01 mm. This comes from constant values which are 11.5 mm rubber wheel diameter and 12 ticks per full rotation. So 1/12 of the wheel circumference are 3.01 mm.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 67 + }, + "hiddenSeries": false, + "id": 54, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Rounds per minute (rpm)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT rpm FROM \"rotary_encoder\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Absolute travel distance (mm)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT dist_meas_mm FROM \"rotary_encoder\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Absolute pulse count", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT pulse FROM \"rotary_encoder\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Distances", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:2058", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:2059", + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The travel distance is a kind of absolute sum which is added/subtracted by rough value 3.01 mm. This comes from constant values which are 11.5 mm rubber wheel diameter and 12 ticks per full rotation. So 1/12 of the wheel circumference are 3.01 mm.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 74 + }, + "hiddenSeries": false, + "id": 118, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Time between two pulses (ms)", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT elapse FROM \"rotary_encoder\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Time between two pulses (ms)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:221", + "decimals": null, + "format": "none", + "label": null, + "logBase": 32, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:222", + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Filament Feed Sensor (Rotary Encoder Keyes KY040)", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 60 + }, + "id": 117, + "panels": [], + "title": "MisfitTech Smart Stepper - Control Modes", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 61 + }, + "hiddenSeries": false, + "id": 97, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:323", + "alias": "torque", + "color": "#F2CC0C" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "torque", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT torque FROM \"SmartStepperA\" WHERE $timeFilter", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "A Drive - torque()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": "127", + "min": "-128", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 61 + }, + "hiddenSeries": false, + "id": 101, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:323", + "alias": "torque", + "color": "#F2CC0C" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "torque", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT torque FROM \"SmartStepperB\" WHERE $timeFilter", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "B Drive - torque()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": "127", + "min": "-128", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 61 + }, + "hiddenSeries": false, + "id": 104, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:323", + "alias": "torque", + "color": "#F2CC0C" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "torque", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT torque FROM \"SmartStepperC\" WHERE $timeFilter", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "C Drive - torque()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": "127", + "min": "-128", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 61 + }, + "hiddenSeries": false, + "id": 107, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:323", + "alias": "torque", + "color": "#F2CC0C" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "torque", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT torque FROM \"SmartStepperD\" WHERE $timeFilter", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "D Drive - torque()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": "127", + "min": "-128", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 68 + }, + "id": 120, + "panels": [], + "title": "MisfitTech Smart Stepper - Positions", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 69 + }, + "hiddenSeries": false, + "id": 90, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#3274D9" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT readpos FROM \"SmartStepperA\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "A Drive - readpos()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 69 + }, + "hiddenSeries": false, + "id": 99, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#3274D9" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT readpos FROM \"SmartStepperB\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "B Drive - readpos()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 69 + }, + "hiddenSeries": false, + "id": 102, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#3274D9" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT readpos FROM \"SmartStepperC\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "C Drive - readpos()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 69 + }, + "hiddenSeries": false, + "id": 108, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#3274D9" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT readpos FROM \"SmartStepperD\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "D Drive - readpos()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 3, + "description": "position = ((200 * Microstepping) / StepsPerUnit) * angleFromSmartStepper / 360.0", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 76 + }, + "hiddenSeries": false, + "id": 105, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#7C2EA3" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT ((200 * 16) / 200) * readpos / 360.0 FROM \"SmartStepperA\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "A Drive - position in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 3, + "description": "position = ((200 * Microstepping) / StepsPerUnit) * angleFromSmartStepper / 360.0", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 76 + }, + "hiddenSeries": false, + "id": 111, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#7C2EA3" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT ((200 * 16) / 200) * readpos / 360.0 FROM \"SmartStepperB\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "B Drive - position in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 3, + "description": "position = ((200 * Microstepping) / StepsPerUnit) * angleFromSmartStepper / 360.0", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 76 + }, + "hiddenSeries": false, + "id": 110, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#7C2EA3" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT ((200 * 16) / 200) * readpos / 360.0 FROM \"SmartStepperC\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "C Drive - position in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 3, + "description": "position = ((200 * Microstepping) / StepsPerUnit) * angleFromSmartStepper / 360.0", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 76 + }, + "hiddenSeries": false, + "id": 109, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:301", + "alias": "readpos", + "color": "#7C2EA3" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "readpos", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT ((200 * 16) / 200) * readpos / 360.0 FROM \"SmartStepperD\" WHERE $timeFilter", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "D Drive - position in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 83 + }, + "id": 95, + "panels": [], + "title": "MisfitTech Smart Stepper - Errors", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 84 + }, + "hiddenSeries": false, + "id": 134, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT serialError FROM \"SmartStepperA\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "A Drive - serial errors", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 84 + }, + "hiddenSeries": false, + "id": 135, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT serialError FROM \"SmartStepperB\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "B Drive - serial errors", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 84 + }, + "hiddenSeries": false, + "id": 136, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT serialError FROM \"SmartStepperC\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "C Drive - serial errors", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 84 + }, + "hiddenSeries": false, + "id": 137, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT serialError FROM \"SmartStepperD\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "D Drive - serial errors", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 91 + }, + "hiddenSeries": false, + "id": 98, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror FROM \"SmartStepperA\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "A Drive - geterror()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 91 + }, + "hiddenSeries": false, + "id": 100, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror FROM \"SmartStepperB\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "B Drive - geterror()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 91 + }, + "hiddenSeries": false, + "id": 103, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror FROM \"SmartStepperC\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "C Drive - geterror()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "The error can get really high (360 degrees and more. But they are not displayed in the graph to flatten the view)", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 91 + }, + "hiddenSeries": false, + "id": 112, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror FROM \"SmartStepperD\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' and $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "D Drive - geterror()", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "arclength", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 98 + }, + "hiddenSeries": false, + "id": 106, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror / 180.0 * 3.1415926535 * 65.0 FROM \"SmartStepperA\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "A Drive - error in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "arclength", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 98 + }, + "hiddenSeries": false, + "id": 114, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror / 180.0 * 3.1415926535 * 65.0 FROM \"SmartStepperB\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "B Drive - error in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "arclength", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 98 + }, + "hiddenSeries": false, + "id": 115, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror / 180.0 * 3.1415926535 * 65.0 FROM \"SmartStepperC\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "C Drive - error in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "description": "arclength", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 98 + }, + "hiddenSeries": false, + "id": 113, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:236", + "alias": "geterror", + "color": "#E02F44" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "geterror", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT geterror / 180.0 * 3.1415926535 * 65.0 FROM \"SmartStepperD\" WHERE $timeFilter", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "D Drive - error in mm", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:515", + "decimals": null, + "format": "lengthmm", + "label": null, + "logBase": 1, + "max": "5", + "min": "-5", + "show": true + }, + { + "$$hashKey": "object:516", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 105 + }, + "id": 56, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": null, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 21 + }, + "hiddenSeries": false, + "id": 96, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "X", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'gyro_x' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Y", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'gyro_y' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Z", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'gyro_z' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ceiling module - gyro - raw values", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": null, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 28 + }, + "hiddenSeries": false, + "id": 50, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "X deg/s", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'gyro_x_scaled' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Y deg/s", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'gyro_y_scaled' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Z deg/s", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'gyro_z_scaled' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ceiling module - gyro - scaled values", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": null, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 35 + }, + "hiddenSeries": false, + "id": 51, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "X", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'accel_x' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Y", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'accel_y' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Z", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'accel_z' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ceiling module - accelerometer - raw values", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": null, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 42 + }, + "hiddenSeries": false, + "id": 52, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "X m/s²", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'accel_x_scaled' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Y m/s²", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'accel_y_scaled' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Z m/s²", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'accel_z_scaled' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ceiling module - accelerometer - scaled values", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": null, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 49 + }, + "hiddenSeries": false, + "id": 53, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "°C", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"mpu6050_value\" WHERE \"type_instance\" = 'temp' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ceiling module - temperature sensor", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "decimals": null, + "format": "none", + "label": "", + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "GY-512 MPU-6050 InvenSense", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 106 + }, + "id": 92, + "panels": [], + "title": "GY-250 MPU-9250 InvenSense", + "type": "row" + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 107 + }, + "id": 32, + "panels": [], + "title": "Raspberry Pi 3 Model B Rev 1.2", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 108 + }, + "hiddenSeries": false, + "id": 6, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Short", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "system", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"load_shortterm\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "load1" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Medium", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "system", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"load_midterm\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "load5" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Long", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "system", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"load_longterm\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "load15" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Load Average", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1778", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1779", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 108 + }, + "hiddenSeries": false, + "id": 5, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideZero": true, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "CPU $tag_instance $tag_type_instance", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "cpu", + "orderByTime": "ASC", + "policy": "default", + "query": "select derivative(mean(value),1s) AS idle from \"cpu_value\" WHERE \"type\" = 'cpu' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval), instance, type_instance fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "usage_guest" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1812", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:1813", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 118 + }, + "hiddenSeries": false, + "id": 10, + "isNew": true, + "legend": { + "alignAsTable": false, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "forks", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "kernel", + "orderByTime": "ASC", + "policy": "default", + "query": "select derivative(mean(value), 1s) from \"processes_value\" WHERE \"type\" = 'fork_rate' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "processes_forked" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Forks", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1730", + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:1731", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 118 + }, + "hiddenSeries": false, + "id": 8, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "used", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "mem", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"memory_value\" WHERE \"type_instance\" = 'used' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "used" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "free", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "mem", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"memory_value\" WHERE \"type_instance\" = 'free' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "free" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "buffered", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "mem", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"memory_value\" WHERE \"type_instance\" = 'buffered' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "buffered" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "cached", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "mem", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"memory_value\" WHERE \"type_instance\" = 'cached' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "cached" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "slab_recl", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"memory_value\" WHERE \"type_instance\" = 'slab_recl' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + }, + { + "alias": "slab_unrecl", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"memory_value\" WHERE \"type_instance\" = 'slab_unrecl' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "F", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "(Stacked) Memory Distribution", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1696", + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:1697", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": 1, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 125 + }, + "hiddenSeries": false, + "id": 15, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Used Swap", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"swap_value\" WHERE \"type\" = 'swap' AND \"type_instance\" = 'used' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Cached Swap", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"swap_value\" WHERE \"type\" = 'swap' AND \"type_instance\" = 'cached' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "free" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Free Swap", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"swap_value\" WHERE \"type\" = 'swap' AND \"type_instance\" = 'free' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "(Stacked) Swap Space", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1627", + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:1628", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 125 + }, + "hiddenSeries": false, + "id": 9, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "running", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "processes", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"processes_value\" WHERE \"type_instance\" = 'running' AND \"type\" = 'ps_state' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "running" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "blocked", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "processes", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"processes_value\" WHERE \"type_instance\" = 'blocked' AND \"type\" = 'ps_state' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "blocked" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "sleeping", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"processes_value\" WHERE \"type_instance\" = 'sleeping' AND \"type\" = 'ps_state' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + }, + { + "alias": "stopped", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"processes_value\" WHERE \"type_instance\" = 'stopped' AND \"type\" = 'ps_state' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + }, + { + "alias": "paging", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"processes_value\" WHERE \"type_instance\" = 'paging' AND \"type\" = 'ps_state' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + }, + { + "alias": "zombies", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(value) from \"processes_value\" WHERE \"type_instance\" = 'zombies' AND \"type\" = 'ps_state' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "F", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "(Stacked) Processes", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1579", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:1580", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": 1, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 132 + }, + "hiddenSeries": false, + "id": 12, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "$tag_type_instance interrupts", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "kernel", + "orderByTime": "ASC", + "policy": "default", + "query": "select derivative(mean(value),1s) from \"irq_value\" WHERE \"type\" = 'irq' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval), \"type_instance\" fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "interrupts" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Interrupts", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1510", + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:1511", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 132 + }, + "hiddenSeries": false, + "id": 25, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "$tag_instance Free", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(value) FROM \"df_value\" WHERE \"type_instance\" = 'free' AND \"type\" = 'df_complex' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval), \"instance\" fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": [], + "timeFrom": "2w", + "timeRegions": [], + "timeShift": null, + "title": "Disk Free Space", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 80 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "10s", + "now" + ] + }, + "reducer": { + "params": [], + "type": "avg" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "0m", + "frequency": "10s", + "handler": 1, + "name": "hangprinter-pi CPU Temperature alert", + "noDataState": "keep_state", + "notifications": [ + { + "uid": "42PfNEiRz" + }, + { + "uid": "ye2notZgk" + } + ] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": 1, + "description": "The official operating temperature limit of the SoC is 85°C. it will throttle performance around 80°C.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 3, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 140 + }, + "hiddenSeries": false, + "id": 47, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "$$hashKey": "object:304", + "alias": "Raspberry Pi CPU Temperature", + "color": "#8F3BB8" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Raspberry Pi CPU Temperature", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select mean(*) from \"cpu_temp_value\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time(60s)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 80 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Raspberry Pi CPU Temperature", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:317", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:318", + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 140 + }, + "hiddenSeries": false, + "id": 16, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Swap Page In", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select derivative(mean(value),1s) from \"swap_value\" WHERE \"type\" = 'swap_io' AND \"type_instance\" = 'in' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "in" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Swap Page Out", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select derivative(mean(value),1s) from \"swap_value\" WHERE \"type\" = 'swap_io' AND \"type_instance\" = 'out' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval) fill(null)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "out" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Swap I/O", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1476", + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "$$hashKey": "object:1477", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 147 + }, + "hiddenSeries": false, + "id": 93, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "%user", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(val_user) FROM \"iostat\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "in" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "%nice", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(val_nice) FROM \"iostat\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "in" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "%system", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(val_system) FROM \"iostat\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "in" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "%iowait", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(val_iowait) FROM \"iostat\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "in" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "%steal", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(val_steal) FROM \"iostat\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "in" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "%idle", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(val_idle) FROM \"iostat\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "F", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "in" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "iostat", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:312", + "decimals": 0, + "format": "percent", + "label": null, + "logBase": 1, + "max": "100", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:313", + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "alert": { + "alertRuleTags": {}, + "conditions": [ + { + "evaluator": { + "params": [ + 0.9 + ], + "type": "gt" + }, + "operator": { + "type": "and" + }, + "query": { + "params": [ + "A", + "10s", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + }, + { + "evaluator": { + "params": [ + 0.9 + ], + "type": "gt" + }, + "operator": { + "type": "or" + }, + "query": { + "params": [ + "B", + "10s", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + }, + { + "evaluator": { + "params": [ + 0.9 + ], + "type": "gt" + }, + "operator": { + "type": "or" + }, + "query": { + "params": [ + "B", + "10s", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + }, + { + "evaluator": { + "params": [ + 0.9 + ], + "type": "gt" + }, + "operator": { + "type": "or" + }, + "query": { + "params": [ + "D", + "10s", + "now" + ] + }, + "reducer": { + "params": [], + "type": "max" + }, + "type": "query" + } + ], + "executionErrorState": "alerting", + "for": "0m", + "frequency": "10s", + "handler": 1, + "name": "Power States (vcgencmd) alert", + "noDataState": "keep_state", + "notifications": [ + { + "uid": "42PfNEiRz" + }, + { + "uid": "ye2notZgk" + } + ] + }, + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": 1, + "description": "Undervoltage events, combined with throttling may happen while rebooting the device. So a possible device reboot can be seen by those peaks. However, please have a look at the uptime value for exactness.", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 3, + "fillGradient": 9, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 154 + }, + "hiddenSeries": false, + "id": 48, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "throttled", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(*) from \"pwr_states_value\" WHERE \"type_instance\" = 'throttled' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "armfreq_capped", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(*) from \"pwr_states_value\" WHERE \"type_instance\" = 'armfreq_capped' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "undervoltage", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(*) from \"pwr_states_value\" WHERE \"type_instance\" = 'undervoltage' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "soft_temp_limit", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(*) from \"pwr_states_value\" WHERE \"type_instance\" = 'soft_temp_limit' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [ + { + "colorMode": "critical", + "fill": true, + "line": true, + "op": "gt", + "value": 0.9 + } + ], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Power States (vcgencmd)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1283", + "decimals": null, + "format": "none", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:1284", + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| COLLECTD}", + "decimals": 1, + "description": "- PSU is active off by default\n- LED is active on by default\n\nThe graph shows 0 not if the device is switched on or off. It only shows the boolean state of the relay!", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 161 + }, + "hiddenSeries": false, + "id": 46, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Led Spots on/off", + "color": "#FADE2A" + }, + { + "alias": "Power Supply Unit (PSU) on/off", + "color": "#F2495C" + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "alias": "Led Spots on/off", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(value) from \"relay_states_value\" WHERE \"type_instance\" = 'pin_ledspot' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Power Supply Unit (PSU) on/off", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "select last(value) from \"relay_states_value\" WHERE \"type_instance\" = 'pin_psu' AND \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Relay States", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:1228", + "decimals": 0, + "format": "none", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:1229", + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 168 + }, + "id": 89, + "panels": [], + "title": "USB Devices", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_INFLUXDB_| TRIKARUS}", + "decimals": 0, + "description": "0 = offline, 1 = online\nIf one or all motors are offline 230 V source power might have been disconnected or some other problem occured. Please also have a look at Duet Controller voltage. Please not that this does not monitor any UART bugs in communication between Raspberry PI and USB interfaces!", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 1, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 169 + }, + "hiddenSeries": false, + "id": 49, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": false, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Smart Stepper - A Drive", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(a_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Smart Stepper - B Drive", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(b_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Smart Stepper - C Drive", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(c_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Smart Stepper - D Drive", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(d_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Duet 2 Ethernet", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(duet_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "Logitech C920 Webcam", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(webcam_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "F", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "USB 4 Port Hub", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(hub_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "G", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + }, + { + "alias": "USB Stick 32GB SanDisk", + "dsType": "influxdb", + "expr": "", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "swap", + "orderByTime": "ASC", + "policy": "default", + "query": "SELECT last(stick_avail) FROM \"usb_devices\" WHERE \"host\" = 'hangprinter-pi.fablabchemnitz.de' AND $timeFilter GROUP BY time($interval)", + "rawQuery": true, + "refId": "H", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "total" + ], + "type": "field" + }, + { + "params": [], + "type": "last" + } + ] + ], + "tags": [ + { + "key": "host", + "operator": "=~", + "value": "/^$host$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": "1d", + "timeRegions": [], + "timeShift": null, + "title": "USB Device Availibility Status History", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:294", + "decimals": 0, + "format": "none", + "label": "", + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "$$hashKey": "object:295", + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": "30s", + "schemaVersion": 25, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "collectd/InfluxDB Metrics", + "uid": "xW5kn7zRz", + "version": 105 +} \ No newline at end of file diff --git a/grafana/grafana-hangprinter.jpg b/grafana/grafana-hangprinter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..906ffe9797fb2c6b41e81c89ce363a06c0aea47b GIT binary patch literal 3306435 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
9k!&3UCB#w- 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
YZIv>)%n9z&W(`?gb! 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≧4&KZcz4KapCl!bc**Qm$i>O0)l-u)SO6uVB|S8 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

  • F4Pz!m%J{tZzWnY5J7bJW3O%Q{7w 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