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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
-
-
+
+
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
-
-
+
+
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
+
+
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 @@
-
-
-
-
+
+
+
+
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 @@
-
-
-
-
+
+
+
+
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 @@
-
-
+
+
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 @@
-
-
-
-
+
+
+
+
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 @@
-
-
+
+
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