Navigation

    • Register
    • Login
    • Search
    • OpenHardware.io
    • Categories
    • Recent
    • Tags
    • Popular
    1. Home
    2. Ethan Chua
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups

    Ethan Chua

    @Ethan Chua

    4
    Reputation
    12
    Posts
    2
    Profile views
    0
    Followers
    0
    Following
    Joined Last Online

    Ethan Chua Follow

    Best posts made by Ethan Chua

    • Sporadic issues finding parent gateway

      Hi all!

      Recently I tried my hand out at MySensors as I was looking for a low-power solution for small sensors where power sockets were not readily available.

      I started off by creating a simple Serial Gateway to be connected to the Rasppi running HA OS with the YAML configuration as shown:

      mysensors: 
        gateways:
          - device: '/dev/ttyUSB0'
            persistence_file: 'mysensors/mysensors.json'
            baud_rate: 115200
        optimistic: false
        persistence: true
        version: 2.3.2
          
      logger: 
        default: error
        logs:
          mysensors: debug
          homeassistant.components.mysensors: debug
      

      I uploaded the standard Serial Gateway sketch to the Arduino Nano serving as the Serial Gateway after doing some minor edits to the inclusion mode and LED indicators:

      (Removed description text)
      
      // Enable debug prints to serial monitor
      #define MY_DEBUG
      
      // Enable and select radio type attached
      #define MY_RADIO_RF24
      //#define MY_RADIO_NRF5_ESB
      //#define MY_RADIO_RFM69
      //#define MY_RADIO_RFM95
      
      // Set LOW transmit power level as default, if you have an amplified NRF-module and
      // power your radio separately with a good regulator you can turn up PA level.
      #define MY_RF24_PA_LEVEL RF24_PA_LOW
      
      // Enable serial gateway
      #define MY_GATEWAY_SERIAL
      
      // Define a lower baud rate for Arduinos running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender)
      #if F_CPU == 8000000L
      #define MY_BAUD_RATE 38400
      #endif
      
      // Enable inclusion mode
      #define MY_INCLUSION_MODE_FEATURE
      // Enable Inclusion mode button on gateway
      //#define MY_INCLUSION_BUTTON_FEATURE
      
      // Inverses behavior of inclusion button (if using external pullup)
      //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
      
      // Set inclusion mode duration (in seconds)
      #define MY_INCLUSION_MODE_DURATION 60
      // Digital pin used for inclusion mode button
      //#define MY_INCLUSION_MODE_BUTTON_PIN  3
      
      // Set blinking period
      #define MY_DEFAULT_LED_BLINK_PERIOD 300
      
      // Inverses the behavior of leds
      //#define MY_WITH_LEDS_BLINKING_INVERSE
      
      // Flash leds on rx/tx/err
      // Uncomment to override default HW configurations
      //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
      //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
      //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
      
      #include <MySensors.h>
      
      void setup()
      {
      	// Setup locally attached sensors
      }
      
      void presentation()
      {
      	// Present locally attached sensors
      }
      
      void loop()
      {
      	// Send locally attached sensor data here
      }
      

      as well as a simple LightSensor example sketch to an arduino nano via breadboard:

      // Enable debug prints to serial monitor
      #define MY_DEBUG
      
      // Enable and select radio type attached
      #define MY_RADIO_RF24
      //#define MY_RADIO_NRF5_ESB
      //#define MY_RADIO_RFM69
      //#define MY_RADIO_RFM95
      
      #include <MySensors.h>
      
      #define CHILD_ID_LIGHT 0
      #define LIGHT_SENSOR_ANALOG_PIN 0
      
      uint32_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
      
      MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
      int lastLightLevel;
      
      
      void presentation()
      {
      	// Send the sketch version information to the gateway and Controller
      	sendSketchInfo("Light Sensor", "1.0");
      
      	// Register all sensors to gateway (they will be created as child devices)
      	present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
      }
      
      void loop()
      {
      	int16_t lightLevel = (1023-analogRead(LIGHT_SENSOR_ANALOG_PIN))/10.23;
      	Serial.println(lightLevel);
      	if (lightLevel != lastLightLevel) {
      		send(msg.set(lightLevel));
      		lastLightLevel = lightLevel;
      	}
      	sleep(SLEEP_TIME);
      }
      

      For both setups power for the Radio module is being sourced from the 3v3 pins of the respective nanos.

      Viewing the Serial log from the node, I observed that the node was consistently failing to find the parent and so I moved the two setups closer and also hooked up the gateway to another instance of IDE to view the serial logs from there. It seems that for some reason only very small snippets of comms are being transferred sporadically between the two.

      The serial logs on the node are as follows:

      | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
      | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
      |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
              |___/                      2.3.2
      
      16 MCO:BGN:INIT NODE,CP=RNNNA---,FQ=16,REL=255,VER=2.3.2
      26 TSM:INIT
      28 TSF:WUR:MS=0
      34 TSM:INIT:TSP OK
      36 TSM:FPAR
      38 ?TSF:MSG:SEND,255-255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
      2048 !TSM:FPAR:NO REPLY
      2050 TSM:FPAR
      2052 ?TSF:MSG:SEND,255-255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
      4060 !TSM:FPAR:NO REPLY
      4062 TSM:FPAR
      4064 ?TSF:MSG:SEND,255-255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
      6072 !TSM:FPAR:NO REPLY
      6074 TSM:FPAR
      6076 ?TSF:MSG:SEND,255-255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
      8084 !TSM:FPAR:FAIL
      8085 TSM:FAIL:CNT=1
      8087 TSM:FAIL:DIS
      8089 TSF:TDI:TSL
      

      and for the gateway:

      0;255;3;0;9;0 MCO:BGN:INIT GW,CP=RNNGA---,FQ=16,REL=255,VER=2.3.2
      0;255;3;0;9;5 TSM:INIT
      0;255;3;0;9;7 TSF:WUR:MS=0
      0;255;3;0;9;15 TSM:INIT:TSP OK
      0;255;3;0;9;18 TSM:INIT:GW MODE
      0;255;3;0;9;21 TSM:READY:ID=0,PAR=0,DIS=0
      0;255;3;0;9;24 MCO:REG:NOT NEEDED
      0;255;3;0;14;Gateway startup complete.
      0;255;0;0;18;2.3.2
      0;255;3;0;9;28 MCO:BGN:STP
      0;255;3;0;9;35 MCO:BGN:INIT OK,TSP=1
      0;255;3;0;9;38 TSM:READY:NWD REQ
      0;255;3;0;9;45 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
      0;255;3;0;9;84532 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;84538 TSF:MSG:BC
      0;255;3;0;9;84540 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;84544 TSF:PNG:SEND,TO=0
      0;255;3;0;9;84547 TSF:CKU:OK
      0;255;3;0;9;84550 TSF:MSG:GWL OK
      0;255;3;0;9;85140 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;206804 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;206812 TSF:MSG:BC
      0;255;3;0;9;206814 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;206818 TSF:PNG:SEND,TO=0
      0;255;3;0;9;206821 TSF:CKU:OK
      0;255;3;0;9;206824 TSF:MSG:GWL OK
      0;255;3;0;9;207832 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;210833 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;210839 TSF:MSG:BC
      0;255;3;0;9;210842 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;210846 TSF:CKU:OK,FCTRL
      0;255;3;0;9;210849 TSF:MSG:GWL OK
      0;255;3;0;9;211787 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;279139 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;279145 TSF:MSG:BC
      0;255;3;0;9;279147 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;279151 TSF:PNG:SEND,TO=0
      0;255;3;0;9;279154 TSF:CKU:OK
      0;255;3;0;9;279157 TSF:MSG:GWL OK
      0;255;3;0;9;279795 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;281152 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;281159 TSF:MSG:BC
      0;255;3;0;9;281161 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;281165 TSF:CKU:OK,FCTRL
      0;255;3;0;9;281168 TSF:MSG:GWL OK
      0;255;3;0;9;281769 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;283166 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;283172 TSF:MSG:BC
      0;255;3;0;9;283175 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;283180 TSF:CKU:OK,FCTRL
      0;255;3;0;9;283183 TSF:MSG:GWL OK
      0;255;3;0;9;283751 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;297221 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;297228 TSF:MSG:BC
      0;255;3;0;9;297230 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;297234 TSF:PNG:SEND,TO=0
      0;255;3;0;9;297237 TSF:CKU:OK
      0;255;3;0;9;297240 TSF:MSG:GWL OK
      0;255;3;0;9;297528 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;363339 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;363346 TSF:MSG:BC
      0;255;3;0;9;363348 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;363353 TSF:PNG:SEND,TO=0
      0;255;3;0;9;363356 TSF:CKU:OK
      0;255;3;0;9;363359 TSF:MSG:GWL OK
      0;255;3;0;9;364230 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;5;1
      0;255;3;0;9;435504 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;435510 TSF:MSG:BC
      0;255;3;0;9;435513 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;435516 TSF:PNG:SEND,TO=0
      0;255;3;0;9;435520 TSF:CKU:OK
      0;255;3;0;9;435522 TSF:MSG:GWL OK
      0;255;3;0;9;435853 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;5;0
      0;255;3;0;9;501621 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;501627 TSF:MSG:BC
      0;255;3;0;9;501630 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;501635 TSF:PNG:SEND,TO=0
      0;255;3;0;9;501638 TSF:CKU:OK
      0;255;3;0;9;501641 TSF:MSG:GWL OK
      0;255;3;0;9;502553 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;505652 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;505658 TSF:MSG:BC
      0;255;3;0;9;505661 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;505664 TSF:CKU:OK,FCTRL
      0;255;3;0;9;505668 TSF:MSG:GWL OK
      0;255;3;0;9;506512 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;639902 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;639908 TSF:MSG:BC
      0;255;3;0;9;639911 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;639915 TSF:PNG:SEND,TO=0
      0;255;3;0;9;639919 TSF:CKU:OK
      0;255;3;0;9;639921 TSF:MSG:GWL OK
      0;255;3;0;9;640875 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;842288 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;842294 TSF:MSG:BC
      0;255;3;0;9;842297 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;842300 TSF:PNG:SEND,TO=0
      0;255;3;0;9;842304 TSF:CKU:OK
      0;255;3;0;9;842306 TSF:MSG:GWL OK
      0;255;3;0;9;842894 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      0;255;3;0;9;900008 TSF:SAN:OK
      0;255;3;0;9;976541 TSF:MSG:READ,255-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0:
      0;255;3;0;9;976547 TSF:MSG:BC
      0;255;3;0;9;976550 TSF:MSG:FPAR REQ,ID=255
      0;255;3;0;9;976555 TSF:PNG:SEND,TO=0
      0;255;3;0;9;976558 TSF:CKU:OK
      0;255;3;0;9;976560 TSF:MSG:GWL OK
      0;255;3;0;9;977257 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=8,pt=1,l=1,sg=0,ft=0,st=OK:0
      

      Occasionally though some data gets through because the green light on the gateway LED will flash and it is also reflected in the gateway logs but there is no consistency or pattern to which I can predict when this will happen.

      Things that I have tried:

      • Soldering the nRF24L01 to the pins of the board via perfboard to eliminate issues with the jumper wires
      • attaching 100uF between 3v3 and GND

      Things I am thinking of trying:

      • Using a dedicated 3.3V supply for the nRF24L01s
      • giving up on 2.4GHz altogether and trying my luck with 433mHz

      At this juncture I highly suspect the issue to be with the quality of my nRF24L01 or the power supply. However if someone has encountered this issue before and would be able to share their experience, I would be more than grateful as this would save me a lot on guesswork.

      Thanks!

      Cheers,
      Ethan

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • RE: Sketch seemingly "hangs" while executing

      Hi there,

      Thanks for the replies! It seemed that the culprit was my stupidity. I forgot that the AccelStepper library's stepper.moveTo() function's argument was the absolute rather than the relative position of the stepper motor. As such my code would end up trying to push the stepper motor to extreme values (because I thought I needed to input a negative to move to the left etc) and this caused weird things to happen, most likely this crashing as well.

      In any case I'm glad the issue has been resolved.

      @electrik the programme takes up 72% of storage space and 64% of dynamic memory, so I will definitely cut out the Serial logs once I am done debugging.

      @mfalkvidd yikes you're right it seems I had forgotten to include the function to run the steppers. Anyways for reference sake I'll drop my final code here (from the last I tested it is working but with the minor issue of the motors having to travel to the end of their move before it can reverse direction, which I have no clue why it happens but I don't mind it):

      #include <AccelStepper.h>
      
      const byte dirPin1 = A0;
      const byte stepPin1 = A1;
      const byte enPin1 = A2;
      const byte dirPin2 = A3;
      const byte stepPin2 = A4;
      const byte enPin2 = A5;
      const byte dirPin3 = 4;
      const byte stepPin3 = 3;
      const byte enPin3 = 8;
      const byte dirPin4 = 7;
      const byte stepPin4 = 6;
      const byte enPin4 = 5;
      const bool enOne = true, enTwo = true, enThree = true, enFour = true;
      const bool dirOne = true, dirTwo = true, dirThree = true, dirFour = true;
      const int stepmmOne = 160, stepmmTwo = 160, stepmmThree = 160, stepmmFour = 160;
      
      const byte endstopup = A6, endstopdown = A7;
      
      //long timer = 0;
      
      #define motorInterfaceType 1
       AccelStepper stepperOne(motorInterfaceType, stepPin1, dirPin1);
       AccelStepper stepperTwo(motorInterfaceType, stepPin2, dirPin2);
       AccelStepper stepperThree(motorInterfaceType, stepPin3, dirPin3);
       AccelStepper stepperFour(motorInterfaceType, stepPin4, dirPin4);
      
      #define MY_DEBUG
      #define MY_RADIO_RF24
      #include <MySensors.h>
      #define CHILD_ID 0
      //#define MY_TRANSPORT_WAIT_READY_MS 1000
      
      int currentShutterLevel = 0, desiredShutterLevel = 0;
      enum currentState {
        STOP,
        UP,
        DOWN,
      };
      static int currentState = STOP; //the initial state is STOP because it is not moving
      boolean requested = false;
      boolean isAlrMoving = false;
      boolean initialValueSent = false;
      boolean receivedStop = false;
      
      int totalDist = 150; //in mm
      int stepsPerMM = 160;
      int currentSteps = 0;
      int desiredSteps = 0;
      int stepsToMove = 0, oldStepsToMove = 0;
      int levelsToMove = 0;
      int levelsToGo = 0;
      int savedShutterLevel = 0;
      int stepSpeed = 50;
      int stepAccel = 1000;
      
      MyMessage upMessage(CHILD_ID, V_UP);
      MyMessage downMessage(CHILD_ID, V_DOWN);
      MyMessage stopMessage(CHILD_ID, V_STOP);
      MyMessage percMessage(CHILD_ID, V_PERCENTAGE);
      
      void sendState(){
        #ifdef MY_DEBUG
          Serial.println("Sending states: ");
          Serial.print("UP: "); Serial.println(currentState == UP);
          Serial.print("DOWN: "); Serial.println(currentState == DOWN);
          Serial.print("STOP: "); Serial.println(currentState == STOP);
          Serial.print("PERC: "); 
          Serial.println(currentShutterLevel);
        #endif
        send(upMessage.set(currentState == UP));
        send(downMessage.set(currentState == DOWN));
        send(stopMessage.set(currentState == STOP));
        send(percMessage.set(desiredShutterLevel));
      }
      void setup() {
      Serial.begin(115200);
      stepperOne.setEnablePin(enPin1);
      stepperOne.setPinsInverted(dirOne,false,enOne);
      stepperOne.setMaxSpeed(stepSpeed);
      stepperOne.setAcceleration(stepAccel);
      //stepperOne.setSpeed(50);
      
      stepperTwo.setEnablePin(enPin2);
      stepperTwo.setPinsInverted(dirTwo,false,enTwo);
      stepperTwo.setMaxSpeed(stepSpeed);
      stepperTwo.setAcceleration(stepAccel);
      //stepperTwo.setSpeed(50);
      
      stepperThree.setEnablePin(enPin3);
      stepperThree.setPinsInverted(dirThree,false,enThree);
      stepperThree.setMaxSpeed(stepSpeed);
      stepperThree.setAcceleration(stepAccel);
      //stepperThree.setSpeed(50);;
      
      stepperFour.setEnablePin(enPin4);
      stepperFour.setPinsInverted(dirFour,false,enFour);
      stepperFour.setMaxSpeed(stepSpeed);
      stepperFour.setAcceleration(stepAccel);
      //stepperFour.setSpeed(50);
      
      pinMode(endstopup, INPUT_PULLUP);
      pinMode(endstopdown, INPUT_PULLUP);
      }
      
      void presentation()
      {
        sendSketchInfo("Hydroponics Stepper Motors", "1.0");
        wait(1000);
        present(CHILD_ID, S_COVER);
      }
      
      void loop() {
        /*if(!initialValueSent){
          #ifdef MY_DEBUG
            Serial.println("Sending initial values!");
          #endif
          sendState();
          initialValueSent = true;
        }
        */
        
        //requesting percentage of height
        if(!requested){
          request(CHILD_ID, V_PERCENTAGE);
          #ifdef MY_DEBUG
            Serial.println("Requesting initial position of lights");
          #endif
        }
          if(currentShutterLevel != desiredShutterLevel || receivedStop){ //allow the setting of new positions if a STOP is called 
          //currentShutterLevel and desiredShutterLevel are used to detect the change in parameters
          if(!isAlrMoving){ //this ensures the following code is only executed once
            enableAllSteppers();
            stepsToMove = map(desiredShutterLevel,0,100,0,totalDist*stepsPerMM);
            Serial.print("Moving to: "); Serial.println(stepsToMove);
            moveAllSteppers(stepsToMove);
            isAlrMoving = true; 
            sendState();
          }
          if(stepperOne.distanceToGo() != 0){
          } else{
              currentShutterLevel = desiredShutterLevel;
              currentState = STOP;
              sendState();
              disableAllSteppers();
          }
          receivedStop = false;
          }else{ //if desired and current are the same - either because there is no movement or when we call STOP, then check to see 
            //if there was a change in the state of STOP. If there was then send the state.
          if(receivedStop){
          sendState();
          receivedStop = false;
          }
          disableAllSteppers();
        }
        runAllSteppers();
        if(analogRead(endstopup)>10 && currentState == UP){ //if the top endstop is triggered and the shutter was moving up
            #ifdef MY_DEBUG
              Serial.println("Top Endstop has been activated!");
            #endif
          receivedStop = true;
          setCurrentPositionofAll(100);
          desiredShutterLevel = 100;
          currentShutterLevel = 100;
          currentState = STOP;
        } else if(analogRead(endstopdown)>10 && currentState == DOWN){ //if the bottom endstop is triggered and the shutter was moving down
          #ifdef MY_DEBUG
              Serial.println("Bottom Endstop has been activated!");
          #endif
          receivedStop = true;
          setCurrentPositionofAll(0);
          desiredShutterLevel = 0;
          currentShutterLevel = 0;
          currentState = STOP;
        }
       
      }
      void receive(const MyMessage &message)
      {
      #ifdef MY_DEBUG
        Serial.print("Received a message from sensor: ");
        Serial.println(String(message.sensor));
        Serial.print("Message type: ");
        Serial.println(String(message.type));
      #endif
      isAlrMoving = false; //since if we receive a message it means that we need to do something, we can allow the position to be reset
        if(message.sensor == CHILD_ID){
          switch(message.type){
            case V_UP:
              desiredShutterLevel = 100;
              currentState = UP;
              #ifdef MY_DEBUG
                Serial.println("Shutter State is UP");
                Serial.print("currentShutterLevel = "); Serial.println(currentShutterLevel);
                Serial.print("desiredShutterLevel = "); Serial.println(desiredShutterLevel);
              #endif
              break;
              
            case V_DOWN:
              desiredShutterLevel = 0;
              currentState = DOWN;
              #ifdef MY_DEBUG
                Serial.println("Shutter State is DOWN");
                Serial.print("currentShutterLevel = "); Serial.println(currentShutterLevel);
                Serial.print("desiredShutterLevel = "); Serial.println(desiredShutterLevel);
              #endif
              break;
              
            case V_STOP:
              receivedStop = true; //allow the loop to send states once
              currentShutterLevel = map(stepperOne.currentPosition(),-totalDist*stepsPerMM,totalDist*stepsPerMM,-100,100); //update the current state with the state that the stepper is actually at
              desiredShutterLevel = currentShutterLevel; //stop the steppers
              currentState = STOP;
              #ifdef MY_DEBUG
                Serial.print("Halt called! Stopping all motors at pos: "); Serial.println(currentShutterLevel);
              #endif
              break;
      
            case V_PERCENTAGE:
              int pos = message.getInt();
              if(pos > 100) pos = 100;
              if(pos < 0) pos = 0;
              if(!requested){
                currentShutterLevel = pos;
                desiredShutterLevel = pos;
                setCurrentPositionofAll(map(pos,0,100,0,totalDist*stepsPerMM));
                #ifdef MY_DEBUG
                  Serial.print("Initialized! Current Shutter Level Set to: "); Serial.println(currentShutterLevel);
                #endif
                requested = true;
              } else{
                desiredShutterLevel = pos;
              }
              currentState = (desiredShutterLevel > currentShutterLevel)?UP:DOWN;
              #ifdef MY_DEBUG
                Serial.print("Shutter State is PERC = "); Serial.println(desiredShutterLevel);
                Serial.print("currentShutterLevel = "); Serial.println(currentShutterLevel);
                Serial.print("desiredShutterLevel = "); Serial.println(desiredShutterLevel);
              #endif
              break;
         }
        }
        #ifdef MY_DEBUG
          Serial.print("Exiting this message with currentState = "); Serial.println(currentState);
        #endif
      }
      void enableAllSteppers(void){
        stepperOne.enableOutputs();
        stepperTwo.enableOutputs();
        stepperThree.enableOutputs();
        stepperFour.enableOutputs();
      }
      void moveAllSteppers(int steps){
        stepperOne.moveTo(steps);
        stepperTwo.moveTo(steps);
        stepperThree.moveTo(steps);
        stepperFour.moveTo(steps);
      }
      void runAllSteppers(void){
        stepperOne.run();
        stepperTwo.run();
        stepperThree.run();
        stepperFour.run();
      }
      void disableAllSteppers(void){
        stepperOne.disableOutputs();
        stepperTwo.disableOutputs();
        stepperThree.disableOutputs();
        stepperFour.disableOutputs();  
      }
      void setCurrentPositionofAll(int pos){
        stepperOne.setCurrentPosition(pos);
        stepperTwo.setCurrentPosition(pos);
        stepperThree.setCurrentPosition(pos);
        stepperFour.setCurrentPosition(pos);
      }
      

      Thanks so much for your patience and suggestions!

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • RE: ENC28J60 Ethernet Shield HA reporting !GWT:TSA:ETH FAIL

      After seeing this thread I think I will just give up on this ENC28J60 and get a W5500 instead.

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • RE: ENC28J60 Ethernet Shield HA reporting !GWT:TSA:ETH FAIL

      @mfalkvidd said in ENC28J60 Ethernet Shield HA reporting !GWT:TSA:ETH FAIL:

      @Ethan-Chua I have never used Home Assistant, but it looks like the configuration tells HA to connect to a MySensors gateway server at 192.168.0.167 while the gateway is configured to start as a client and connect to a server at 192.168.0.153. So there are 2 clients, each trying to connect to a server that doesn't exist.

      If that's the case, removing this part should make the connection work:

      // Controller ip address. Enables client mode (default is "server" mode). 
      // Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere. 
      #define MY_CONTROLLER_IP_ADDRESS 192,168,0,153  
      

      Ok I must have misunderstood the meaning of MY_CONTROLLER_IP_ADDRESS. Will try and see how it goes.

      Thanks!

      UPDATE: It works now thanks @mfalkvidd for your help!

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua

    Latest posts made by Ethan Chua

    • RE: ENC28J60 Ethernet Shield HA reporting !GWT:TSA:ETH FAIL

      @mfalkvidd said in ENC28J60 Ethernet Shield HA reporting !GWT:TSA:ETH FAIL:

      @Ethan-Chua I have never used Home Assistant, but it looks like the configuration tells HA to connect to a MySensors gateway server at 192.168.0.167 while the gateway is configured to start as a client and connect to a server at 192.168.0.153. So there are 2 clients, each trying to connect to a server that doesn't exist.

      If that's the case, removing this part should make the connection work:

      // Controller ip address. Enables client mode (default is "server" mode). 
      // Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere. 
      #define MY_CONTROLLER_IP_ADDRESS 192,168,0,153  
      

      Ok I must have misunderstood the meaning of MY_CONTROLLER_IP_ADDRESS. Will try and see how it goes.

      Thanks!

      UPDATE: It works now thanks @mfalkvidd for your help!

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • RE: ENC28J60 Ethernet Shield HA reporting !GWT:TSA:ETH FAIL

      After seeing this thread I think I will just give up on this ENC28J60 and get a W5500 instead.

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • ENC28J60 Ethernet Shield HA reporting !GWT:TSA:ETH FAIL

      Hi there,

      Recently I tried building a RF24 MySensors Ethernet Gateway using a ENC28J60 Nano shield. I had to remap all of the SPI pins of the NRF24L01 (unlike this guide) as the ENC28J60 shield was not playing nice while sharing the MOSI,MISO and SCK pins of the RF24.

      RF24 Pins:
      Pin | From IO | To IO
      CE 9 5
      CS 10 6
      MOSI 11 9
      MISO 12 8
      SCK 13 3
      IRQ 2 2 (no change)
      This was based off this guide which stated that only D10,11,12 & 13 were used for these ENC28J60 nano ethernet shields.

      However now the issue is that although the Ethernet Shield can connect to the network (I can see it's IP on my router dashboard and successfully ping that IP), MY_DEBUG keeps throwing !GWT:TSA:ETH FAIL errors and adding the Gateway to HA has been unsuccessful:
      MySensors Integration Unsuccessful.PNG

      Here is my Gateway Arduino Sketch:

      /**
       * The MySensors Arduino library handles the wireless radio link and protocol
       * between your home built sensors/actuators and HA controller of choice.
       * The sensors forms a self healing radio network with optional repeaters. Each
       * repeater and gateway builds a routing tables in EEPROM which keeps track of the
       * network topology allowing messages to be routed to nodes.
       *
       * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
       * Copyright (C) 2013-2015 Sensnology AB
       * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
       *
       * Documentation: http://www.mysensors.org
       * Support Forum: http://forum.mysensors.org
       *
       * This program is free software; you can redistribute it and/or
       * modify it under the terms of the GNU General Public License
       * version 2 as published by the Free Software Foundation.
       *
       *******************************
       *
       * REVISION HISTORY
       * Version 1.0 - Henrik EKblad
       * Contribution by a-lurker and Anticimex,
       * Contribution by Norbert Truchsess <norbert.truchsess@t-online.de>
       * Contribution by Tomas Hozza <thozza@gmail.com>
       *
       *
       * DESCRIPTION
       * The EthernetGateway sends data received from sensors to the ethernet link.
       * The gateway also accepts input on ethernet interface, which is then sent out to the radio network.
       *
       * The GW code is designed for Arduino 328p / 16MHz.  ATmega168 does not have enough memory to run this program.
       *
       * LED purposes:
       * - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h
       * - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
       * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
       * - ERR (red) - fast blink on error during transmission error or recieve crc error
       *
       * See http://www.mysensors.org/build/ethernet_gateway for wiring instructions.
       *
       */
      
      // Enable debug prints to serial monitor
      #define MY_DEBUG 
      
      // Enable and select radio type attached
      #define MY_RADIO_RF24
      //#define MY_RADIO_RFM69
      
      // When ENC28J60 is connected we have to move CE/CSN pins for NRF radio
      #define MY_SOFTSPI
      #define MY_SOFT_SPI_SCK_PIN 3
      #define MY_SOFT_SPI_MISO_PIN 8
      #define MY_SOFT_SPI_MOSI_PIN 9
      #define MY_RF24_CE_PIN 5
      #define MY_RF24_CS_PIN 6
      
      // Enable gateway ethernet module type 
      #define MY_GATEWAY_ENC28J60
      
      // Gateway IP address
      #define MY_IP_ADDRESS 192,168,0,167
      
      // The port to keep open on node server mode / or port to contact in client mode
      #define MY_PORT 5003   
      
      // Controller ip address. Enables client mode (default is "server" mode). 
      // Also enable this if MY_USE_UDP is used and you want sensor data sent somewhere. 
      #define MY_CONTROLLER_IP_ADDRESS 192,168,0,153  
       
      // The MAC address can be anything you want but should be unique on your network.
      // Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use.
      // Note that most of the Ardunio examples use  "DEAD BEEF FEED" for the MAC address.
      #define MY_MAC_ADDRESS 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
      
      // Set blinking period
      #define MY_DEFAULT_LED_BLINK_PERIOD 300
      
      // Enable inclusion mode
      #define MY_INCLUSION_MODE_FEATURE
      // Enable Inclusion mode button on gateway
      //#define MY_INCLUSION_BUTTON_FEATURE
      // Set inclusion mode duration (in seconds)
      #define MY_INCLUSION_MODE_DURATION 60 
      // Digital pin used for inclusion mode button
      //#define MY_INCLUSION_MODE_BUTTON_PIN  3 
      
      #define MY_DEFAULT_ERR_LED_PIN 7  // Error led pin
      #define MY_DEFAULT_RX_LED_PIN  4  // Receive led pin
      //#define MY_DEFAULT_TX_LED_PIN  3  // the PCB, on board LED
      
      #include <SPI.h>
      #include <UIPEthernet.h>
      #include <MySensors.h>
      
      
      void setup()
      {
      }
      
      void presentation()
      {
        // Present locally attached sensors
      }
      
      void loop() {
      }
      

      A snippet from my config.yaml:

      mysensors: 
        gateways:
          - device: '/dev/ttyUSB0'
            persistence_file: 'mysensors/mysensors.json'
            baud_rate: 115200
          - device: '192.168.0.167'
            persistence_file: 'mysensors/mysensors1.json'
            tcp_port: 5003
        optimistic: false
        persistence: true
        version: 2.3.2
      

      And the MY_DEBUG logs:

      0 MCO:BGN:INIT GW,CP=RNNGA---,FQ=16,REL=255,VER=2.3.2
      4 TSM:INIT
      5 TSF:WUR:MS=0
      12 TSM:INIT:TSP OK
      13 TSM:INIT:GW MODE
      15 TSM:READY:ID=0,PAR=0,DIS=0
      18 MCO:REG:NOT NEEDED
      71 GWT:TIN:IP=192.168.0.167
      1576 !GWT:TIN:ETH FAIL
      1579 MCO:BGN:STP
      1581 MCO:BGN:INIT OK,TSP=1
      2077 !GWT:TSA:ETH FAIL
      2079 TSM:READY:NWD REQ
      2084 ?TSF:MSG:SEND,0-0-255-255,s=255,c=3,t=20,pt=0,l=0,sg=0,ft=0,st=OK:
      2576 !GWT:TSA:ETH FAIL
      3077 !GWT:TSA:ETH FAIL
      3079 TSF:MSG:READ,1-1-0,s=255,c=3,t=21,pt=1,l=1,sg=0:0
      3576 !GWT:TPS:ETH FAIL
      3578 TSF:MSG:READ,0-1-255,s=255,c=3,t=20,pt=0,l=0,sg=0:
      3584 TSF:MSG:BC
      4077 !GWT:TSA:ETH FAIL
      4576 !GWT:TSA:ETH FAIL
      5076 !GWT:TSA:ETH FAIL
      5577 !GWT:TSA:ETH FAIL
      6076 !GWT:TSA:ETH FAIL
      6577 !GWT:TSA:ETH FAIL
      7076 !GWT:TSA:ETH FAIL
      7579 !GWT:TSA:ETH FAIL
      8076 !GWT:TSA:ETH FAIL
      8577 !GWT:TSA:ETH FAIL
      

      Other things I have tried:

      • Swapping out RF24 boards (but from the MY_DEBUG logs it seems the RF24 is not the problem)
      • Downgrading the AVR Boards to 1.6.11 as per this guide but failed as the sketch failed to compile. Error: multiple libraries found for SPI.h.
      • Powering the board via a external power supply
      • Tried both UIPEthernet Libraries (the one from MySensorsArduinoExamples and the one from ntruchsess

      Perhaps it could be that the sketch occupies 80% of storage (with MY_DEBUG)? I am on the verge of just giving up with this problematic setup and use ESP8266 MQTT instead.

      I would like to hear from anyone who has tried a similar setup! Thanks!

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • RE: Increasing range of 8MHz ATMEGA328P with NRF24L01

      @Larson
      Hi may I know what Board setup you are using? I am using the MiniCore Board "Library" and apart from the BOD fuse setting I don't see any other voltage option.
      Could you share the board library you are using, worth giving it a shot to see if that helps. Thanks.
      Minicore

      posted in Hardware
      Ethan Chua
      Ethan Chua
    • RE: Increasing range of 8MHz ATMEGA328P with NRF24L01

      @monte Hi there thanks for pointing this out. I went back to have a look at the PCB files and it turns out I messed up the .brd file while probing around which resulted in the GND wire stub.

      The actual board has a GND plane on the bottom layer like so:
      PCB layout.PNG

      posted in Hardware
      Ethan Chua
      Ethan Chua
    • RE: Increasing range of 8MHz ATMEGA328P with NRF24L01

      Hi, I tested the setup with both a lab bench power supply as well as a BL8530 boost converter IC to boost two AA batteries to 3.3V.

      posted in Hardware
      Ethan Chua
      Ethan Chua
    • RE: Sketch seemingly "hangs" while executing

      Hi there,

      Thanks for the replies! It seemed that the culprit was my stupidity. I forgot that the AccelStepper library's stepper.moveTo() function's argument was the absolute rather than the relative position of the stepper motor. As such my code would end up trying to push the stepper motor to extreme values (because I thought I needed to input a negative to move to the left etc) and this caused weird things to happen, most likely this crashing as well.

      In any case I'm glad the issue has been resolved.

      @electrik the programme takes up 72% of storage space and 64% of dynamic memory, so I will definitely cut out the Serial logs once I am done debugging.

      @mfalkvidd yikes you're right it seems I had forgotten to include the function to run the steppers. Anyways for reference sake I'll drop my final code here (from the last I tested it is working but with the minor issue of the motors having to travel to the end of their move before it can reverse direction, which I have no clue why it happens but I don't mind it):

      #include <AccelStepper.h>
      
      const byte dirPin1 = A0;
      const byte stepPin1 = A1;
      const byte enPin1 = A2;
      const byte dirPin2 = A3;
      const byte stepPin2 = A4;
      const byte enPin2 = A5;
      const byte dirPin3 = 4;
      const byte stepPin3 = 3;
      const byte enPin3 = 8;
      const byte dirPin4 = 7;
      const byte stepPin4 = 6;
      const byte enPin4 = 5;
      const bool enOne = true, enTwo = true, enThree = true, enFour = true;
      const bool dirOne = true, dirTwo = true, dirThree = true, dirFour = true;
      const int stepmmOne = 160, stepmmTwo = 160, stepmmThree = 160, stepmmFour = 160;
      
      const byte endstopup = A6, endstopdown = A7;
      
      //long timer = 0;
      
      #define motorInterfaceType 1
       AccelStepper stepperOne(motorInterfaceType, stepPin1, dirPin1);
       AccelStepper stepperTwo(motorInterfaceType, stepPin2, dirPin2);
       AccelStepper stepperThree(motorInterfaceType, stepPin3, dirPin3);
       AccelStepper stepperFour(motorInterfaceType, stepPin4, dirPin4);
      
      #define MY_DEBUG
      #define MY_RADIO_RF24
      #include <MySensors.h>
      #define CHILD_ID 0
      //#define MY_TRANSPORT_WAIT_READY_MS 1000
      
      int currentShutterLevel = 0, desiredShutterLevel = 0;
      enum currentState {
        STOP,
        UP,
        DOWN,
      };
      static int currentState = STOP; //the initial state is STOP because it is not moving
      boolean requested = false;
      boolean isAlrMoving = false;
      boolean initialValueSent = false;
      boolean receivedStop = false;
      
      int totalDist = 150; //in mm
      int stepsPerMM = 160;
      int currentSteps = 0;
      int desiredSteps = 0;
      int stepsToMove = 0, oldStepsToMove = 0;
      int levelsToMove = 0;
      int levelsToGo = 0;
      int savedShutterLevel = 0;
      int stepSpeed = 50;
      int stepAccel = 1000;
      
      MyMessage upMessage(CHILD_ID, V_UP);
      MyMessage downMessage(CHILD_ID, V_DOWN);
      MyMessage stopMessage(CHILD_ID, V_STOP);
      MyMessage percMessage(CHILD_ID, V_PERCENTAGE);
      
      void sendState(){
        #ifdef MY_DEBUG
          Serial.println("Sending states: ");
          Serial.print("UP: "); Serial.println(currentState == UP);
          Serial.print("DOWN: "); Serial.println(currentState == DOWN);
          Serial.print("STOP: "); Serial.println(currentState == STOP);
          Serial.print("PERC: "); 
          Serial.println(currentShutterLevel);
        #endif
        send(upMessage.set(currentState == UP));
        send(downMessage.set(currentState == DOWN));
        send(stopMessage.set(currentState == STOP));
        send(percMessage.set(desiredShutterLevel));
      }
      void setup() {
      Serial.begin(115200);
      stepperOne.setEnablePin(enPin1);
      stepperOne.setPinsInverted(dirOne,false,enOne);
      stepperOne.setMaxSpeed(stepSpeed);
      stepperOne.setAcceleration(stepAccel);
      //stepperOne.setSpeed(50);
      
      stepperTwo.setEnablePin(enPin2);
      stepperTwo.setPinsInverted(dirTwo,false,enTwo);
      stepperTwo.setMaxSpeed(stepSpeed);
      stepperTwo.setAcceleration(stepAccel);
      //stepperTwo.setSpeed(50);
      
      stepperThree.setEnablePin(enPin3);
      stepperThree.setPinsInverted(dirThree,false,enThree);
      stepperThree.setMaxSpeed(stepSpeed);
      stepperThree.setAcceleration(stepAccel);
      //stepperThree.setSpeed(50);;
      
      stepperFour.setEnablePin(enPin4);
      stepperFour.setPinsInverted(dirFour,false,enFour);
      stepperFour.setMaxSpeed(stepSpeed);
      stepperFour.setAcceleration(stepAccel);
      //stepperFour.setSpeed(50);
      
      pinMode(endstopup, INPUT_PULLUP);
      pinMode(endstopdown, INPUT_PULLUP);
      }
      
      void presentation()
      {
        sendSketchInfo("Hydroponics Stepper Motors", "1.0");
        wait(1000);
        present(CHILD_ID, S_COVER);
      }
      
      void loop() {
        /*if(!initialValueSent){
          #ifdef MY_DEBUG
            Serial.println("Sending initial values!");
          #endif
          sendState();
          initialValueSent = true;
        }
        */
        
        //requesting percentage of height
        if(!requested){
          request(CHILD_ID, V_PERCENTAGE);
          #ifdef MY_DEBUG
            Serial.println("Requesting initial position of lights");
          #endif
        }
          if(currentShutterLevel != desiredShutterLevel || receivedStop){ //allow the setting of new positions if a STOP is called 
          //currentShutterLevel and desiredShutterLevel are used to detect the change in parameters
          if(!isAlrMoving){ //this ensures the following code is only executed once
            enableAllSteppers();
            stepsToMove = map(desiredShutterLevel,0,100,0,totalDist*stepsPerMM);
            Serial.print("Moving to: "); Serial.println(stepsToMove);
            moveAllSteppers(stepsToMove);
            isAlrMoving = true; 
            sendState();
          }
          if(stepperOne.distanceToGo() != 0){
          } else{
              currentShutterLevel = desiredShutterLevel;
              currentState = STOP;
              sendState();
              disableAllSteppers();
          }
          receivedStop = false;
          }else{ //if desired and current are the same - either because there is no movement or when we call STOP, then check to see 
            //if there was a change in the state of STOP. If there was then send the state.
          if(receivedStop){
          sendState();
          receivedStop = false;
          }
          disableAllSteppers();
        }
        runAllSteppers();
        if(analogRead(endstopup)>10 && currentState == UP){ //if the top endstop is triggered and the shutter was moving up
            #ifdef MY_DEBUG
              Serial.println("Top Endstop has been activated!");
            #endif
          receivedStop = true;
          setCurrentPositionofAll(100);
          desiredShutterLevel = 100;
          currentShutterLevel = 100;
          currentState = STOP;
        } else if(analogRead(endstopdown)>10 && currentState == DOWN){ //if the bottom endstop is triggered and the shutter was moving down
          #ifdef MY_DEBUG
              Serial.println("Bottom Endstop has been activated!");
          #endif
          receivedStop = true;
          setCurrentPositionofAll(0);
          desiredShutterLevel = 0;
          currentShutterLevel = 0;
          currentState = STOP;
        }
       
      }
      void receive(const MyMessage &message)
      {
      #ifdef MY_DEBUG
        Serial.print("Received a message from sensor: ");
        Serial.println(String(message.sensor));
        Serial.print("Message type: ");
        Serial.println(String(message.type));
      #endif
      isAlrMoving = false; //since if we receive a message it means that we need to do something, we can allow the position to be reset
        if(message.sensor == CHILD_ID){
          switch(message.type){
            case V_UP:
              desiredShutterLevel = 100;
              currentState = UP;
              #ifdef MY_DEBUG
                Serial.println("Shutter State is UP");
                Serial.print("currentShutterLevel = "); Serial.println(currentShutterLevel);
                Serial.print("desiredShutterLevel = "); Serial.println(desiredShutterLevel);
              #endif
              break;
              
            case V_DOWN:
              desiredShutterLevel = 0;
              currentState = DOWN;
              #ifdef MY_DEBUG
                Serial.println("Shutter State is DOWN");
                Serial.print("currentShutterLevel = "); Serial.println(currentShutterLevel);
                Serial.print("desiredShutterLevel = "); Serial.println(desiredShutterLevel);
              #endif
              break;
              
            case V_STOP:
              receivedStop = true; //allow the loop to send states once
              currentShutterLevel = map(stepperOne.currentPosition(),-totalDist*stepsPerMM,totalDist*stepsPerMM,-100,100); //update the current state with the state that the stepper is actually at
              desiredShutterLevel = currentShutterLevel; //stop the steppers
              currentState = STOP;
              #ifdef MY_DEBUG
                Serial.print("Halt called! Stopping all motors at pos: "); Serial.println(currentShutterLevel);
              #endif
              break;
      
            case V_PERCENTAGE:
              int pos = message.getInt();
              if(pos > 100) pos = 100;
              if(pos < 0) pos = 0;
              if(!requested){
                currentShutterLevel = pos;
                desiredShutterLevel = pos;
                setCurrentPositionofAll(map(pos,0,100,0,totalDist*stepsPerMM));
                #ifdef MY_DEBUG
                  Serial.print("Initialized! Current Shutter Level Set to: "); Serial.println(currentShutterLevel);
                #endif
                requested = true;
              } else{
                desiredShutterLevel = pos;
              }
              currentState = (desiredShutterLevel > currentShutterLevel)?UP:DOWN;
              #ifdef MY_DEBUG
                Serial.print("Shutter State is PERC = "); Serial.println(desiredShutterLevel);
                Serial.print("currentShutterLevel = "); Serial.println(currentShutterLevel);
                Serial.print("desiredShutterLevel = "); Serial.println(desiredShutterLevel);
              #endif
              break;
         }
        }
        #ifdef MY_DEBUG
          Serial.print("Exiting this message with currentState = "); Serial.println(currentState);
        #endif
      }
      void enableAllSteppers(void){
        stepperOne.enableOutputs();
        stepperTwo.enableOutputs();
        stepperThree.enableOutputs();
        stepperFour.enableOutputs();
      }
      void moveAllSteppers(int steps){
        stepperOne.moveTo(steps);
        stepperTwo.moveTo(steps);
        stepperThree.moveTo(steps);
        stepperFour.moveTo(steps);
      }
      void runAllSteppers(void){
        stepperOne.run();
        stepperTwo.run();
        stepperThree.run();
        stepperFour.run();
      }
      void disableAllSteppers(void){
        stepperOne.disableOutputs();
        stepperTwo.disableOutputs();
        stepperThree.disableOutputs();
        stepperFour.disableOutputs();  
      }
      void setCurrentPositionofAll(int pos){
        stepperOne.setCurrentPosition(pos);
        stepperTwo.setCurrentPosition(pos);
        stepperThree.setCurrentPosition(pos);
        stepperFour.setCurrentPosition(pos);
      }
      

      Thanks so much for your patience and suggestions!

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • RE: Soldering station

      Hi there,

      I have been using this cheap one and it has been working quite well! However, I recently saw this hotplate reflow station and I think with a proper stencil / fine solder paste needle it would be miles better than using a hot air gun (after being burned countless times from having to hold the SMD pieces with a tweezer while blowing). Will try building one (albeit shorter as I want it to fit under my electronics microscope) and will let y'all have a look once it's done!

      posted in General Discussion
      Ethan Chua
      Ethan Chua
    • RE: Sporadic issues finding parent gateway

      Hi there,

      Thanks for your response! It turns out I needed a better 3.3V power supply because I was powering the NRF24L01 from the Nano's 3.3V pin which is derived from the CH340 USB-Serial converter and is not ideal. Upgrading the supply to an AMS1117 3.3V supply solved the issue completely!

      Sorry for the late reply and thanks so much for your tips! Will try them out if issues crop up in the future.

      posted in Troubleshooting
      Ethan Chua
      Ethan Chua
    • Increasing range of 8MHz ATMEGA328P with NRF24L01

      Hi there,

      Recently I designed a PCB as a PIR Motion Sensor Board for my home automation project. The aim was to mount a couple of these around the house on the ceiling so that the lights in my house could be motion-activated/deactivated (I already have wired up a bunch of relays to my mains using ESPHome, Home Assistant).

      However, after soldering everything up I was unable to get the node to communicate with the gateway at all. After some head-banging, I finally changed the NRF24L01 module from the short one (image 1) to the longer one with the "high power" and PA LNA capabilities (image 2) and bingo the gateway started receiving messages from my node.

      Image 1 - Small Board
      Image 2 - Large Board

      However, the range is severely limited (to about a few meters) and once I move the gateway back to its original spot (Raspberry Pi) the comms fail again...

      I have created various end nodes using Arduino Nanos (5V) with the "small" NRF24L01 boards (even my gateway) and they all work great, even at much longer ranges.

      Specs:

      Microcontroller: ATMEGA328P
      Frequency: 8MHz
      Voltage: 3.3V

      Code

      //Code description was removed for readability
      // Enable debug prints
       #define MY_DEBUG
       #define MY_BAUD_RATE 9600
      
      // Enable and select radio type attached
      #define MY_RADIO_RF24
      #define MY_RF24_PA_LEVEL RF24_PA_LOW
      //#define MY_RADIO_NRF5_ESB
      //#define MY_RADIO_RFM69
      //#define MY_RADIO_RFM95
      
      #include <MySensors.h>
      
      uint32_t SLEEP_TIME = 1000; // Sleep time between reports (in milliseconds)
      #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
      #define LDR_SENSOR_1 A0
      #define LDR_SENSOR_2 A1
      #define BATTERY_SENSE_PIN A2
      
      int oldBatteryPcnt = 0;
      
      // Initialize motion message
      MyMessage motion(0, V_TRIPPED);
      MyMessage firstLDR(1, V_LIGHT_LEVEL);
      MyMessage secondLDR(2, V_LIGHT_LEVEL);
      
      void setup()
      {
        pinMode(DIGITAL_INPUT_SENSOR, INPUT);    
        pinMode(LDR_SENSOR_1, INPUT_PULLUP);
        pinMode(LDR_SENSOR_2, INPUT_PULLUP);
      }
      
      void presentation()
      {
        sendSketchInfo("Motion Sensor", "1.0");
      
        present(0, S_MOTION);
        present(1, S_LIGHT_LEVEL);
        present(2, S_LIGHT_LEVEL);
      }
      
      void loop()
      {
        bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
        int light1 = analogRead(LDR_SENSOR_1);
        int light2 = analogRead(LDR_SENSOR_2); 
        int sensorValue = analogRead(BATTERY_SENSE_PIN);
        int batteryPerc = (sensorValue * 10) / 10230 * 110;
      
        Serial.print("Motion: "); Serial.println(tripped);
        Serial.print("LDR 1: "); Serial.println(light1);
        Serial.print("LDR 2: "); Serial.println(light2);
        Serial.print("Battery Sensor Value: "); Serial.println(sensorValue);
        Serial.print("Battery Percentage: "); Serial.println(batteryPerc);
        
        send(motion.set(tripped?"1":"0"));  // Send tripped value to gw
        send(firstLDR.set(light1));
        send(secondLDR.set(light2));
      
        if(oldBatteryPcnt != batteryPerc){
          sendBatteryLevel(batteryPerc);
          oldBatteryPcnt = batteryPerc;
        }
      
      	// Sleep until interrupt comes in on motion sensor. Send update every ten minutes.
      	sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);
      }
      

      What I have tried doing

      • The wiring is definitely correct as I checked continuity on all the 328P's and NRF24L01's pins
      • Cleared EEPROM according to this
      • Swapped around "small" NRF24L01 modules with end nodes that are confirmed to be working
      • Added 47uF cap across the NRF24L01's supply pins
      • Added a 22AWG wire to connect the NRF24L01's supply pins directly to the voltage input (to rule out resistance of the traces)
      • Defined #define MY_RF24_PA_LEVEL RF24_PA_LOW

      What I suspect is the problem
      Given that all my other end nodes work fine with the "small" NRF24L01, I suspect it is:

      • 3.3V logic level (although the NRF24L01 should be 3.3V logic level as well)
      • 8MHz frequency (I observed that the "small" NRF24L01 modules have a 16MHz crystal)
      • My board layout (notably traces being too thin / too many crisscrossing signal paths, vias etc)

      I have attached the .brd and .sch files (EAGLE) here for those who would be willing to take a look at them.

      I would be most appreciative of any advice, especially from anyone who has tried their hand at a similar setup as mine.

      Thanks!

      posted in Hardware
      Ethan Chua
      Ethan Chua