From 0fdd5dcf9e8408e7c3ecf5cb0bcf12486004913c Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Sun, 8 Aug 2021 14:43:38 +0200 Subject: [PATCH] updated printer profile --- .../stepper_nano_zero/.cproject | 244 +- .../stepper_nano_zero/.project | 68 +- .../stepper_nano_zero/A1333.cpp | 304 +- .../stepper_nano_zero/A1333.h | 118 +- .../stepper_nano_zero/A4954.cpp | 824 +- .../stepper_nano_zero/A4954.h | 180 +- .../stepper_nano_zero/A5995.cpp | 674 +- .../stepper_nano_zero/A5995.h | 184 +- .../stepper_nano_zero/Adafruit_GFX.cpp | 2142 +- .../stepper_nano_zero/Adafruit_GFX.h | 310 +- .../stepper_nano_zero/Adafruit_SSD1306.cpp | 1500 +- .../stepper_nano_zero/Adafruit_SSD1306.h | 364 +- .../stepper_nano_zero/Flash.cpp | 384 +- .../stepper_nano_zero/Flash.h | 136 +- .../stepper_nano_zero/angle.h | 294 +- .../stepper_nano_zero/as5047d.cpp | 644 +- .../stepper_nano_zero/as5047d.h | 116 +- .../stepper_nano_zero/board.h | 1128 +- .../stepper_nano_zero/calibration.cpp | 1198 +- .../stepper_nano_zero/calibration.h | 208 +- .../stepper_nano_zero/command.cpp | 762 +- .../stepper_nano_zero/command.h | 358 +- .../stepper_nano_zero/commands.cpp | 3316 +- .../stepper_nano_zero/commands.h | 102 +- .../stepper_nano_zero/eeprom.cpp | 618 +- .../stepper_nano_zero/eeprom.h | 124 +- .../stepper_nano_zero/fet_driver.cpp | 3370 +- .../stepper_nano_zero/fet_driver.h | 248 +- .../stepper_nano_zero/ftoa.cpp | 386 +- .../stepper_nano_zero/ftoa.h | 96 +- .../stepper_nano_zero/gfxfont.h | 48 +- .../stepper_nano_zero/glcdfont.c | 552 +- .../stepper_nano_zero/nonvolatile.cpp | 290 +- .../stepper_nano_zero/nonvolatile.h | 216 +- .../stepper_nano_zero/nzs.cpp | 1804 +- .../stepper_nano_zero/nzs.h | 106 +- .../stepper_nano_zero/nzs_lcd.cpp | 1200 +- .../stepper_nano_zero/nzs_lcd.h | 180 +- .../stepper_nano_zero/planner.cpp | 414 +- .../stepper_nano_zero/planner.h | 136 +- .../stepper_nano_zero/sine.cpp | 396 +- .../stepper_nano_zero/sine.h | 86 +- .../stepper_nano_zero/stepper_controller.cpp | 3902 +-- .../stepper_nano_zero/stepper_controller.h | 448 +- .../stepper_nano_zero/stepper_nano_zero.ino | 26 +- .../stepper_nano_zero/steppin.cpp | 628 +- .../stepper_nano_zero/steppin.h | 62 +- .../stepper_nano_zero/syslog.cpp | 486 +- .../stepper_nano_zero/syslog.h | 420 +- .../stepper_nano_zero/utils.cpp | 90 +- .../stepper_nano_zero/utils.h | 78 +- grafana/collectd_InfluxDB Metrics.json | 28168 ++++++++-------- inkscape_drawings/alignment-60-degrees.svg | 518 +- inkscape_drawings/alignment-misalignment.svg | 630 +- inkscape_drawings/anchor-points.svg | 1128 +- inkscape_drawings/anchor-positioning.svg | 7110 ++-- inkscape_drawings/bearing-shearoff.svg | 2126 +- inkscape_drawings/build-volume-collisions.svg | 1740 +- inkscape_drawings/build-volume.svg | 1878 +- .../coordinate-system-minimized.svg | 872 +- inkscape_drawings/coordinate-system.svg | 918 +- inkscape_drawings/d-drive-unit.svg | 358 +- inkscape_drawings/effector-angles.svg | 4576 +-- .../effector-coordinate-system.svg | 2460 +- inkscape_drawings/effector-d-offset.svg | 918 +- inkscape_drawings/effector-line-angle.svg | 802 +- inkscape_drawings/effector-line-guiding.svg | 630 +- inkscape_drawings/effector-tool-offsets.svg | 2090 +- inkscape_drawings/feature-double-lines.svg | 1488 +- inkscape_drawings/feature-single-lines.svg | 982 +- inkscape_drawings/frame-validation.svg | 1540 +- inkscape_drawings/hangprinter.svg | 1706 +- inkscape_drawings/line-lengths.svg | 4362 +-- inkscape_drawings/main-drawing.svg | 5220 +-- inkscape_drawings/measuring-XY.svg | 3432 +- inkscape_drawings/measuring-Z.svg | 2040 +- inkscape_drawings/pivot-points.svg | 2220 +- inkscape_drawings/platform.svg | 176 +- inkscape_drawings/print diameter.svg | 758 +- inkscape_drawings/print volume-shapes.svg | 362 +- inkscape_drawings/random-positions.svg | 1950 +- inkscape_drawings/spool-buildup.svg | 1436 +- inkscape_drawings/spool-line-deflection.svg | 784 +- .../Trikarus - Redline Filament PLA.ini | 8 +- prusaslicer_profile/print/Trikarus.ini | 38 +- prusaslicer_profile/printer/Trikarus.ini | 8 +- 86 files changed, 58700 insertions(+), 58700 deletions(-) diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/.cproject b/firmware_smartstepper_trikarus/stepper_nano_zero/.cproject index 114531f..9287844 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/.cproject +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/.cproject @@ -1,122 +1,122 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/.project b/firmware_smartstepper_trikarus/stepper_nano_zero/.project index 41a61b6..2345921 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/.project +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/.project @@ -1,34 +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 - - - + + + 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 index 168493d..4a67513 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.cpp @@ -1,152 +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; -} +/********************************************************************** + 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 index ee9ee68..83430ec 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A1333.h @@ -1,59 +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_ */ +/********************************************************************** + 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 index 61388a4..e920d1c 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.cpp @@ -1,412 +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 - +/********************************************************************** + 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 index c66decb..4590ea9 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A4954.h @@ -1,90 +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__ +/********************************************************************** + 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 index f2b8a9f..faeafb7 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.cpp @@ -1,337 +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 - - - +/********************************************************************** + 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 index 756513c..8b99791 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/A5995.h @@ -1,92 +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_ */ +/********************************************************************** + 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 index 46d4d54..3628ba3 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_GFX.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_GFX.cpp @@ -1,1071 +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 +#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 +#ifndef _ADAFRUIT_GFX_H +#define _ADAFRUIT_GFX_H + +#if ARDUINO >= 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 index 2a78892..1ae6a1d 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.cpp @@ -1,750 +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; - } - } -} +/********************************************************************* +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 index 7d7a5fe..24ffcc5 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Adafruit_SSD1306.h @@ -1,182 +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_ */ +/********************************************************************* +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 index 2604732..d40beac 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.cpp @@ -1,192 +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) { } - } - - -} +/********************************************************************** + 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 index c95d700..f144fd6 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/Flash.h @@ -1,68 +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__ +/********************************************************************** + 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 index 34e0226..6232a42 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/angle.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/angle.h @@ -1,147 +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_ */ +/********************************************************************** + 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 index 0812c36..8879c9e 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.cpp @@ -1,322 +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 - +/********************************************************************** + 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 index 8252c93..4ab1666 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/as5047d.h @@ -1,58 +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__ +/********************************************************************** + 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 index cd7a87d..9a9c59f 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/board.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/board.h @@ -1,564 +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__ +/********************************************************************** +/********************************************************************** + 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 index e9ae16c..523be92 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.cpp @@ -1,599 +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; -} - - +/********************************************************************** + 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 index eaba5a6..bcadc6b 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/calibration.h @@ -1,104 +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__ +/********************************************************************** + 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 index bc6412a..cd4079e 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/command.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/command.cpp @@ -1,381 +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; -} - +/********************************************************************** + 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 index 3af3df2..4b6ecdf 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/command.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/command.h @@ -1,179 +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 - +/********************************************************************** + 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 index a6c1c56..17872c7 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/commands.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/commands.cpp @@ -1,1658 +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 -} - +/********************************************************************** + 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 index 3edef45..f1a3517 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/commands.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/commands.h @@ -1,51 +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__ +/********************************************************************** + 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 index e82b3fb..b44cf7d 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.cpp @@ -1,309 +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; -} +/********************************************************************** + 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 index 75154eb..4a4a08f 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/eeprom.h @@ -1,62 +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_ */ +/********************************************************************** + 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 index cfe9b4e..ce47e24 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.cpp @@ -1,1685 +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 +/********************************************************************** + 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 index a056897..816f847 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/fet_driver.h @@ -1,124 +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_ */ +/********************************************************************** + 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 index 8ff7f42..637dac1 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.cpp @@ -1,193 +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 - } +/********************************************************************** + 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 index 55000ff..d7ea3b5 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/ftoa.h @@ -1,48 +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_ */ +/********************************************************************** + 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 index 07381ed..2245094 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/gfxfont.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/gfxfont.h @@ -1,24 +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_ +// 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 index 6f88bd2..01e51fc 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/glcdfont.c +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/glcdfont.c @@ -1,276 +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 +// 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 index 32d5465..5a138d6 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.cpp @@ -1,145 +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 -} - +/********************************************************************** + 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 index 3e29c03..d9149eb 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nonvolatile.h @@ -1,108 +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__ +/********************************************************************** + 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 index cc2dbbd..39f15df 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.cpp @@ -1,902 +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 +/* + * 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 index a21904d..27d1cde 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs.h @@ -1,53 +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_ */ +/* + * 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 index b29051c..2c90824 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.cpp @@ -1,600 +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]); - } - } -} - - +/* + * 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 index c3c4bac..ea3097a 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/nzs_lcd.h @@ -1,90 +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_ */ +/* + * 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 index ec37836..fce04cd 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/planner.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/planner.cpp @@ -1,207 +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; -} +/********************************************************************** + * 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 index e80b8b1..bb29935 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/planner.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/planner.h @@ -1,68 +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_ */ +/********************************************************************** + * 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 index 8c2e22c..1a55486 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/sine.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/sine.cpp @@ -1,198 +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 +/* + * 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 index 8a039e4..275da0b 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/sine.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/sine.h @@ -1,43 +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_ */ +/********************************************************************** + * 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 index a88774f..2ab43b6 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_controller.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_controller.cpp @@ -1,1951 +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! + *********************************************************************/ +#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__ - +/********************************************************************** + * 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 __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 index 62794ae..ba24c47 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.ino +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/stepper_nano_zero.ino @@ -1,13 +1,13 @@ -#include "nzs.h" - -NZS nzs; - - -void setup() { - nzs.begin(); -} - - -void loop() { - nzs.loop(); -} +#include "nzs.h" + +NZS nzs; + + +void setup() { + nzs.begin(); +} + + +void loop() { + nzs.loop(); +} diff --git a/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp b/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp index 8eb5659..6af6a62 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.cpp @@ -1,314 +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 - -} +/* + * 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 index 62b13dd..9c716f5 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/steppin.h @@ -1,31 +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___ +/* + * 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 index aaf270d..90c9c6d 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.cpp @@ -1,243 +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; -} +/* + * 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 index acd7b2e..8a80d4e 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/syslog.h @@ -1,210 +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_ */ +/* + * 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 index 144ec2e..1101cac 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/utils.cpp +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/utils.cpp @@ -1,45 +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); -} - - - +/********************************************************************** + * 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 index b8f1a11..6057d47 100644 --- a/firmware_smartstepper_trikarus/stepper_nano_zero/utils.h +++ b/firmware_smartstepper_trikarus/stepper_nano_zero/utils.h @@ -1,39 +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_ */ +/********************************************************************** + * 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 index 5bac6bc..faa09ea 100644 --- a/grafana/collectd_InfluxDB Metrics.json +++ b/grafana/collectd_InfluxDB Metrics.json @@ -1,14085 +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 +{ + "__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/inkscape_drawings/alignment-60-degrees.svg b/inkscape_drawings/alignment-60-degrees.svg index 7fa623b..5000d4c 100644 --- a/inkscape_drawings/alignment-60-degrees.svg +++ b/inkscape_drawings/alignment-60-degrees.svg @@ -1,259 +1,259 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - 60° - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + 60° + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/alignment-misalignment.svg b/inkscape_drawings/alignment-misalignment.svg index d03976f..5b445b6 100644 --- a/inkscape_drawings/alignment-misalignment.svg +++ b/inkscape_drawings/alignment-misalignment.svg @@ -1,315 +1,315 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - angle misalignment - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + angle misalignment + + + + + diff --git a/inkscape_drawings/anchor-points.svg b/inkscape_drawings/anchor-points.svg index 66e7a2a..0517a64 100644 --- a/inkscape_drawings/anchor-points.svg +++ b/inkscape_drawings/anchor-points.svg @@ -1,564 +1,564 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - A anchor point - C anchor point - B anchor point - X - Y - - - - - - - - D anchor point - - Z - - origin line lengths - - - - a - a - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + A anchor point + C anchor point + B anchor point + X + Y + + + + + + + + D anchor point + + Z + + origin line lengths + + + + a + a + + + + diff --git a/inkscape_drawings/anchor-positioning.svg b/inkscape_drawings/anchor-positioning.svg index acd363a..b39cbe8 100644 --- a/inkscape_drawings/anchor-positioning.svg +++ b/inkscape_drawings/anchor-positioning.svg @@ -1,3555 +1,3555 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/bearing-shearoff.svg b/inkscape_drawings/bearing-shearoff.svg index c05c085..6b43b93 100644 --- a/inkscape_drawings/bearing-shearoff.svg +++ b/inkscape_drawings/bearing-shearoff.svg @@ -1,1063 +1,1063 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 22.5° - - regular stress - - - - - - - - - - unreal string guidance - - - 45° - - - - - - - - shear off - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 22.5° + + regular stress + + + + + + + + + + unreal string guidance + + + 45° + + + + + + + + shear off + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/build-volume-collisions.svg b/inkscape_drawings/build-volume-collisions.svg index edd804d..d1b9a4a 100644 --- a/inkscape_drawings/build-volume-collisions.svg +++ b/inkscape_drawings/build-volume-collisions.svg @@ -1,870 +1,870 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - previously printed layer - currently printing layer - line collision - - effector at max. print diameter - - effector at max. print diameter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + previously printed layer + currently printing layer + line collision + + effector at max. print diameter + + effector at max. print diameter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/build-volume.svg b/inkscape_drawings/build-volume.svg index a06341f..8fa2daf 100644 --- a/inkscape_drawings/build-volume.svg +++ b/inkscape_drawings/build-volume.svg @@ -1,939 +1,939 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/coordinate-system-minimized.svg b/inkscape_drawings/coordinate-system-minimized.svg index fd655c0..801f8fd 100644 --- a/inkscape_drawings/coordinate-system-minimized.svg +++ b/inkscape_drawings/coordinate-system-minimized.svg @@ -1,436 +1,436 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - X - Y - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + X + Y + + + + + + + + diff --git a/inkscape_drawings/coordinate-system.svg b/inkscape_drawings/coordinate-system.svg index 4f2a896..bbc3c3f 100644 --- a/inkscape_drawings/coordinate-system.svg +++ b/inkscape_drawings/coordinate-system.svg @@ -1,459 +1,459 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - A anchor - C anchor - B anchor - origin 0,0,0 ("origo") - - X - Y - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + A anchor + C anchor + B anchor + origin 0,0,0 ("origo") + + X + Y + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/d-drive-unit.svg b/inkscape_drawings/d-drive-unit.svg index 2863fc0..5c2d60d 100644 --- a/inkscape_drawings/d-drive-unit.svg +++ b/inkscape_drawings/d-drive-unit.svg @@ -1,179 +1,179 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - spool - coil D1 - coil D2 - coil D3 - motor D drive unit - + + + + + + + + + + image/svg+xml + + + + + + + + + spool + coil D1 + coil D2 + coil D3 + motor D drive unit + diff --git a/inkscape_drawings/effector-angles.svg b/inkscape_drawings/effector-angles.svg index 701e0db..552e3e4 100644 --- a/inkscape_drawings/effector-angles.svg +++ b/inkscape_drawings/effector-angles.svg @@ -1,2288 +1,2288 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - line angle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - line angle - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + line angle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + line angle + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/effector-coordinate-system.svg b/inkscape_drawings/effector-coordinate-system.svg index 9b12533..deafbaa 100644 --- a/inkscape_drawings/effector-coordinate-system.svg +++ b/inkscape_drawings/effector-coordinate-system.svg @@ -1,1230 +1,1230 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - A anchor - B anchor - - - C anchor - B1 - B2 - A2 - A1 - C1 - C2 - - - - - - X - Y - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + A anchor + B anchor + + + C anchor + B1 + B2 + A2 + A1 + C1 + C2 + + + + + + X + Y + + + + + + + + diff --git a/inkscape_drawings/effector-d-offset.svg b/inkscape_drawings/effector-d-offset.svg index 0527a2f..79cd0d4 100644 --- a/inkscape_drawings/effector-d-offset.svg +++ b/inkscape_drawings/effector-d-offset.svg @@ -1,459 +1,459 @@ - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - d - - - D line - - - A line - B line - - - - - + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + d + + + D line + + + A line + B line + + + + + diff --git a/inkscape_drawings/effector-line-angle.svg b/inkscape_drawings/effector-line-angle.svg index 22938da..43acbc1 100644 --- a/inkscape_drawings/effector-line-angle.svg +++ b/inkscape_drawings/effector-line-angle.svg @@ -1,401 +1,401 @@ - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/effector-line-guiding.svg b/inkscape_drawings/effector-line-guiding.svg index 9f1f4dc..ec9fa39 100644 --- a/inkscape_drawings/effector-line-guiding.svg +++ b/inkscape_drawings/effector-line-guiding.svg @@ -1,315 +1,315 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/effector-tool-offsets.svg b/inkscape_drawings/effector-tool-offsets.svg index a947c75..c1eae3a 100644 --- a/inkscape_drawings/effector-tool-offsets.svg +++ b/inkscape_drawings/effector-tool-offsets.svg @@ -1,1045 +1,1045 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - nozzle withxy offset - C - B - A - X - Y - - - - - - y - x - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + nozzle withxy offset + C + B + A + X + Y + + + + + + y + x + + + + + + + + + + + + + + diff --git a/inkscape_drawings/feature-double-lines.svg b/inkscape_drawings/feature-double-lines.svg index 5d68270..f87b631 100644 --- a/inkscape_drawings/feature-double-lines.svg +++ b/inkscape_drawings/feature-double-lines.svg @@ -1,744 +1,744 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - C anchor - C1/C2 line pair from C drive spool - - - C1T pivot point - C2B pivot point - - bottom of line C1 - top of line C1 - bottom of line C2 - top of line C2 - - - - - - - to effector - from effector - to effector - from effector - - - knot - C2T pivot point - - C1B pivot point - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + C anchor + C1/C2 line pair from C drive spool + + + C1T pivot point + C2B pivot point + + bottom of line C1 + top of line C1 + bottom of line C2 + top of line C2 + + + + + + + to effector + from effector + to effector + from effector + + + knot + C2T pivot point + + C1B pivot point + + + + + + diff --git a/inkscape_drawings/feature-single-lines.svg b/inkscape_drawings/feature-single-lines.svg index 33a0640..f9f26b6 100644 --- a/inkscape_drawings/feature-single-lines.svg +++ b/inkscape_drawings/feature-single-lines.svg @@ -1,491 +1,491 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - C1/C2 line pair from C drive spool - - - - - line C1 - line C2 - - - to effector - to effector - C anchor - C1 pivot point - C2 pivot point - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + C1/C2 line pair from C drive spool + + + + + line C1 + line C2 + + + to effector + to effector + C anchor + C1 pivot point + C2 pivot point + + + + diff --git a/inkscape_drawings/frame-validation.svg b/inkscape_drawings/frame-validation.svg index 1162af8..88cccd5 100644 --- a/inkscape_drawings/frame-validation.svg +++ b/inkscape_drawings/frame-validation.svg @@ -1,770 +1,770 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - l - AB - - - l - B - - - l - A - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - l - C - - - l - BC - - l - AC - s - C - s - A - s - B - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + l + AB + + + l + B + + + l + A + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + l + C + + + l + BC + + l + AC + s + C + s + A + s + B + + + diff --git a/inkscape_drawings/hangprinter.svg b/inkscape_drawings/hangprinter.svg index e699bda..1959cfb 100644 --- a/inkscape_drawings/hangprinter.svg +++ b/inkscape_drawings/hangprinter.svg @@ -1,853 +1,853 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - frame - print bed - origin 0,0,0 ("origo") - ceiling unit - effector ("mover") - hotend nozzle tip A1 A2 C2 C1 B2 B1 D1 D2 D3 - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + frame + print bed + origin 0,0,0 ("origo") + ceiling unit + effector ("mover") + hotend nozzle tip A1 A2 C2 C1 B2 B1 D1 D2 D3 + + + + + + + + + + + + + diff --git a/inkscape_drawings/line-lengths.svg b/inkscape_drawings/line-lengths.svg index d6621c9..33ea1d1 100644 --- a/inkscape_drawings/line-lengths.svg +++ b/inkscape_drawings/line-lengths.svg @@ -1,2181 +1,2181 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A1 (A2 or B1 or B2 or C1 or C2) line - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - D1 (D2 or C3) line - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A1 (A2 or B1 or B2 or C1 or C2) line + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + D1 (D2 or C3) line + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/main-drawing.svg b/inkscape_drawings/main-drawing.svg index 923c414..25d112a 100644 --- a/inkscape_drawings/main-drawing.svg +++ b/inkscape_drawings/main-drawing.svg @@ -1,2610 +1,2610 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ceiling unit - - print bed - - A (or B or C) anchor (2 anchors per drive) - - A (or B or C) spool with 2 lines (1 line per coil) - - effector ("mover")at some random position - - hotend nozzle tip - - - - - - - - - - - - - - - - D spool - - - stopping arm / drive transport fixation - - D line tuner - - - - - - - - - - - - - - - - - - A (or B or C) line tuner - - - - Z - print - - Z - 0 - - - - XY - Offset - - h - 2 - - Z - - current - - h - 1 - - - Z - A - - Z - D - - - - - d - - print - effectoraxis - origoaxis - nozzleaxis - - - h - 3 - - - - h - 4 - - - - - - - - - - - - - - - - - - - - (h ) - 4 - h - 5 - - - - - doubled line mechanism(all lines parallel each) - - - - - - ceilingaxis - max - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ceiling unit + + print bed + + A (or B or C) anchor (2 anchors per drive) + + A (or B or C) spool with 2 lines (1 line per coil) + + effector ("mover")at some random position + + hotend nozzle tip + + + + + + + + + + + + + + + + D spool + + + stopping arm / drive transport fixation + + D line tuner + + + + + + + + + + + + + + + + + + A (or B or C) line tuner + + + + Z + print + + Z + 0 + + + + XY + Offset + + h + 2 + + Z + + current + + h + 1 + + + Z + A + + Z + D + + + + + d + + print + effectoraxis + origoaxis + nozzleaxis + + + h + 3 + + + + h + 4 + + + + + + + + + + + + + + + + + + + + (h ) + 4 + h + 5 + + + + + doubled line mechanism(all lines parallel each) + + + + + + ceilingaxis + max + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/measuring-XY.svg b/inkscape_drawings/measuring-XY.svg index 1b43b1f..b36cfc0 100644 --- a/inkscape_drawings/measuring-XY.svg +++ b/inkscape_drawings/measuring-XY.svg @@ -1,1716 +1,1716 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - A anchor point - C anchor point - B anchor point - X - Y - - - - - - - - D anchor point - - Z - - origin line lengths - - - - a - a - - - - - - - C2_A - C2_E - - - - - - - - - - - - - - - - - - - - - - - - - - B - X - - - - - - - - - B - Y - - - - - - - - C - Y - - - - - C - X - - A - Y - - - - A - X - =0 - - - - - - 2 - C1_A - C1_E - B1_A - B2_A - B2_E - B1_E - A2_E - A2_A - - - - - - A anchor - C anchor - B anchor - A1_E - A1_A - - - - - - - X - Y - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + A anchor point + C anchor point + B anchor point + X + Y + + + + + + + + D anchor point + + Z + + origin line lengths + + + + a + a + + + + + + + C2_A + C2_E + + + + + + + + + + + + + + + + + + + + + + + + + + B + X + + + + + + + + + B + Y + + + + + + + + C + Y + + + + + C + X + + A + Y + + + + A + X + =0 + + + + + + 2 + C1_A + C1_E + B1_A + B2_A + B2_E + B1_E + A2_E + A2_A + + + + + + A anchor + C anchor + B anchor + A1_E + A1_A + + + + + + + X + Y + + + + + + + diff --git a/inkscape_drawings/measuring-Z.svg b/inkscape_drawings/measuring-Z.svg index 8e46834..4a49844 100644 --- a/inkscape_drawings/measuring-Z.svg +++ b/inkscape_drawings/measuring-Z.svg @@ -1,1020 +1,1020 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - A - Z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + A + Z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/pivot-points.svg b/inkscape_drawings/pivot-points.svg index 38ee35c..6ee95a1 100644 --- a/inkscape_drawings/pivot-points.svg +++ b/inkscape_drawings/pivot-points.svg @@ -1,1110 +1,1110 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - A anchor - C anchor - B anchor - C2 pivot point - C1 pivot point - A1 pivot point - A2 pivot point - B2 pivot point - B1 pivot point - - - - - - - - - - - - - - - - - - - origin 0,0,0 ("origo") - X - Y - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + A anchor + C anchor + B anchor + C2 pivot point + C1 pivot point + A1 pivot point + A2 pivot point + B2 pivot point + B1 pivot point + + + + + + + + + + + + + + + + + + + origin 0,0,0 ("origo") + X + Y + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/platform.svg b/inkscape_drawings/platform.svg index 5f12778..dbbff68 100644 --- a/inkscape_drawings/platform.svg +++ b/inkscape_drawings/platform.svg @@ -1,88 +1,88 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/inkscape_drawings/print diameter.svg b/inkscape_drawings/print diameter.svg index e932967..28ce165 100644 --- a/inkscape_drawings/print diameter.svg +++ b/inkscape_drawings/print diameter.svg @@ -1,379 +1,379 @@ - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - angle - - d 1 - - d 2 - d 3 - - - - - - - d 4 - - - - - + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + angle + + d 1 + + d 2 + d 3 + + + + + + + d 4 + + + + + diff --git a/inkscape_drawings/print volume-shapes.svg b/inkscape_drawings/print volume-shapes.svg index 406bbb5..e3c03bc 100644 --- a/inkscape_drawings/print volume-shapes.svg +++ b/inkscape_drawings/print volume-shapes.svg @@ -1,181 +1,181 @@ - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inkscape_drawings/random-positions.svg b/inkscape_drawings/random-positions.svg index 97f0d4c..ed10305 100644 --- a/inkscape_drawings/random-positions.svg +++ b/inkscape_drawings/random-positions.svg @@ -1,975 +1,975 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - A anchor point - C anchor point - B anchor point - X - Y - - - - - - - - - D anchor point - - Z - nozzle tip with effectorat random position - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + A anchor point + C anchor point + B anchor point + X + Y + + + + + + + + + D anchor point + + Z + nozzle tip with effectorat random position + + + diff --git a/inkscape_drawings/spool-buildup.svg b/inkscape_drawings/spool-buildup.svg index 2b651fc..d94890d 100644 --- a/inkscape_drawings/spool-buildup.svg +++ b/inkscape_drawings/spool-buildup.svg @@ -1,718 +1,718 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - d line - - b coil - - d coil - - winding 1 winding 2 - - - - - - - - - - d + buildup for winding 1 coil - - - d + buildup for winding 2 coil - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + d line + + b coil + + d coil + + winding 1 winding 2 + + + + + + + + + + d + buildup for winding 1 coil + + + d + buildup for winding 2 coil + + + diff --git a/inkscape_drawings/spool-line-deflection.svg b/inkscape_drawings/spool-line-deflection.svg index ccd9f8e..17aaf90 100644 --- a/inkscape_drawings/spool-line-deflection.svg +++ b/inkscape_drawings/spool-line-deflection.svg @@ -1,392 +1,392 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/prusaslicer_profile/filament/Trikarus - Redline Filament PLA.ini b/prusaslicer_profile/filament/Trikarus - Redline Filament PLA.ini index 26cced8..9082615 100644 --- a/prusaslicer_profile/filament/Trikarus - Redline Filament PLA.ini +++ b/prusaslicer_profile/filament/Trikarus - Redline Filament PLA.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0 on 2021-07-25 at 16:56:32 UTC +# generated by PrusaSlicer 2.2.0 on 2021-08-07 at 12:59:12 UTC bed_temperature = 0 bridge_fan_speed = 100 compatible_printers = Trikarus @@ -6,7 +6,7 @@ compatible_printers_condition = compatible_prints = Trikarus compatible_prints_condition = cooling = 1 -disable_fan_first_layers = 2 +disable_fan_first_layers = 3 end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n" extrusion_multiplier = 0.9 fan_always_on = 1 @@ -45,11 +45,11 @@ filament_unloading_speed_start = 100 filament_vendor = (Unknown) filament_wipe = nil first_layer_bed_temperature = 0 -first_layer_temperature = 210 +first_layer_temperature = 200 inherits = max_fan_speed = 100 min_fan_speed = 65 min_print_speed = 10 slowdown_below_layer_time = 5 start_filament_gcode = "; Filament gcode\n" -temperature = 215 +temperature = 200 diff --git a/prusaslicer_profile/print/Trikarus.ini b/prusaslicer_profile/print/Trikarus.ini index a8265a1..4f769d5 100644 --- a/prusaslicer_profile/print/Trikarus.ini +++ b/prusaslicer_profile/print/Trikarus.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0 on 2021-07-25 at 16:56:30 UTC +# generated by PrusaSlicer 2.2.0 on 2021-08-07 at 13:05:18 UTC avoid_crossing_perimeters = 0 bottom_fill_pattern = concentric bottom_solid_layers = 2 @@ -17,36 +17,36 @@ dont_support_bridges = 1 draft_shield = 0 elefant_foot_compensation = 0.2 ensure_vertical_shell_thickness = 1 -external_perimeter_extrusion_width = 0 +external_perimeter_extrusion_width = 1.57 external_perimeter_speed = 50% external_perimeters_first = 0 extra_perimeters = 1 extruder_clearance_height = 20 extruder_clearance_radius = 20 -extrusion_width = 0 +extrusion_width = 1.57 fill_angle = 45 fill_density = 100% fill_pattern = concentric first_layer_acceleration = 0 -first_layer_extrusion_width = 120% +first_layer_extrusion_width = 150% first_layer_height = 100% -first_layer_speed = 20 -gap_fill_speed = 11 +first_layer_speed = 15 +gap_fill_speed = 20 gcode_comments = 0 gcode_label_objects = 0 infill_acceleration = 0 infill_every_layers = 1 infill_extruder = 1 -infill_extrusion_width = 0 +infill_extrusion_width = 1.57 infill_first = 0 infill_only_where_needed = 0 -infill_overlap = 35% -infill_speed = 45 +infill_overlap = 30% +infill_speed = 33 inherits = interface_shells = 0 layer_height = 1 -max_print_speed = 50 -max_volumetric_speed = 50 +max_print_speed = 33 +max_volumetric_speed = 40 min_skirt_length = 100 notes = only_retract_when_crossing_perimeters = 1 @@ -55,7 +55,7 @@ output_filename_format = [input_filename_base].gcode overhangs = 1 perimeter_acceleration = 0 perimeter_extruder = 1 -perimeter_extrusion_width = 0 +perimeter_extrusion_width = 1.57 perimeter_speed = 33 perimeters = 2 post_process = @@ -68,12 +68,12 @@ skirt_distance = 40 skirt_height = 1 skirts = 1 slice_closing_radius = 0.049 -small_perimeter_speed = 25% +small_perimeter_speed = 15 solid_infill_below_area = 70 solid_infill_every_layers = 0 solid_infill_extruder = 1 -solid_infill_extrusion_width = 0 -solid_infill_speed = 33% +solid_infill_extrusion_width = 1.57 +solid_infill_speed = 20 spiral_vase = 0 standby_temperature_delta = -5 support_material = 1 @@ -83,7 +83,7 @@ support_material_buildplate_only = 0 support_material_contact_distance = 0.2 support_material_enforce_layers = 0 support_material_extruder = 1 -support_material_extrusion_width = 0 +support_material_extrusion_width = 1.22 support_material_interface_contact_loops = 0 support_material_interface_extruder = 1 support_material_interface_layers = 2 @@ -91,7 +91,7 @@ support_material_interface_spacing = 4 support_material_interface_speed = 100% support_material_pattern = rectilinear support_material_spacing = 8 -support_material_speed = 35 +support_material_speed = 33 support_material_synchronize_layers = 0 support_material_threshold = 0 support_material_with_sheath = 1 @@ -99,8 +99,8 @@ support_material_xy_spacing = 50% thin_walls = 1 threads = 6 top_fill_pattern = concentric -top_infill_extrusion_width = 0 -top_solid_infill_speed = 60% +top_infill_extrusion_width = 1.4 +top_solid_infill_speed = 15 top_solid_layers = 4 top_solid_min_thickness = 0 travel_speed = 130 diff --git a/prusaslicer_profile/printer/Trikarus.ini b/prusaslicer_profile/printer/Trikarus.ini index 17d9c60..d2d1ec5 100644 --- a/prusaslicer_profile/printer/Trikarus.ini +++ b/prusaslicer_profile/printer/Trikarus.ini @@ -1,4 +1,4 @@ -# generated by PrusaSlicer 2.2.0 on 2021-07-25 at 16:56:35 UTC +# generated by PrusaSlicer 2.2.0 on 2021-08-03 at 14:29:33 UTC bed_custom_model = /home/tomate/.PrusaSlicer/printer/trikarus-bed.stl bed_custom_texture = /home/tomate/.PrusaSlicer/printer/trikarus-bed.svg bed_shape = 498.097x43.5779,492.404x86.8241,482.963x129.41,469.846x171.01,453.154x211.309,433.013x250,409.576x286.788,383.022x321.394,353.553x353.553,321.394x383.022,286.788x409.576,250x433.013,211.309x453.154,171.01x469.846,129.41x482.963,86.8241x492.404,43.5779x498.097,3.06162e-14x500,-43.5779x498.097,-86.8241x492.404,-129.41x482.963,-171.01x469.846,-211.309x453.154,-250x433.013,-286.788x409.576,-321.394x383.022,-353.553x353.553,-383.022x321.394,-409.576x286.788,-433.013x250,-453.154x211.309,-469.846x171.01,-482.963x129.41,-492.404x86.8241,-498.097x43.5779,-500x6.12323e-14,-498.097x-43.5779,-492.404x-86.8241,-482.963x-129.41,-469.846x-171.01,-453.154x-211.309,-433.013x-250,-409.576x-286.788,-383.022x-321.394,-353.553x-353.553,-321.394x-383.022,-286.788x-409.576,-250x-433.013,-211.309x-453.154,-171.01x-469.846,-129.41x-482.963,-86.8241x-492.404,-43.5779x-498.097,-9.18485e-14x-500,43.5779x-498.097,86.8241x-492.404,129.41x-482.963,171.01x-469.846,211.309x-453.154,250x-433.013,286.788x-409.576,321.394x-383.022,353.553x-353.553,383.022x-321.394,409.576x-286.788,433.013x-250,453.154x-211.309,469.846x-171.01,482.963x-129.41,492.404x-86.8241,498.097x-43.5779,500x-1.22465e-13 @@ -41,7 +41,7 @@ nozzle_diameter = 1.4 parking_pos_retraction = 92 print_host = printer_model = -printer_notes = - M203 command in PrusaSlicer takes mm/second but Duet RRF takes those values as mm/minute. So you need to enter the mm/minute values without conversion\n- M73 not supported by RRF\n- retraction is configured by firmware and is set to M207 S0.8 R0.0 F2500 Z0.8 (0.8 mm) - so we skip to use the suggestion of 3 mm in PrusaSlicer (it is disabled) +printer_notes = - M203 command in PrusaSlicer takes mm/second but Duet RRF takes those values as mm/minute. So you need to enter the mm/minute values without conversion\n- M73 not supported by RRF\n- retraction is configured by firmware and is set to M207 S1.6 R0.0 F2500 Z0.8 (1.6 mm) - so we skip to use the suggestion of 3 mm in PrusaSlicer (it is disabled) printer_settings_id = Trikarus printer_technology = FFF printer_variant = @@ -69,7 +69,7 @@ thumbnails = toolchange_gcode = use_firmware_retraction = 1 use_relative_e_distances = 0 -use_volumetric_e = 1 -variable_layer_height = 1 +use_volumetric_e = 0 +variable_layer_height = 0 wipe = 0 z_offset = 0