PulseIn related function not working

Hey everyone,

I have this function which is not working:

void System::Laser_Output_testing()
{
    duration = pulseIn(LaserStart_IN, HIGH, 1100); //How long is laserStart_pin HIGH (HIGH for longer than 1000 us= laser emission OFF)

    if (duration <= 1000 && duration != 0) //Laser ON
    {

        if (Serial1.available())
        {
            char laser_ABN[32] = "ABN";
            Serial1.write(laser_ABN); // Guide laser ON
            Serial1.write('\r');
            Serial1.write('\n');
        }
    }

    if (duration == 0 || duration > 1000) //Laser OFF
    {
        if (Serial1.available())
        {
            char laser_ABF[32] = "ABF";
            Serial1.write(laser_ABF); // Guide laser OFF
            Serial1.write('\r');
            Serial1.write('\n');
        }
    }
}

I want to read how long the input is HIGH so I can send an instruction to a laser, but nothing is happening. I have an osciloscope and the input signal is OK, but the arduino is not responding to the signal. I do not know if it is not running the function or if it is always setting my laser to OFF.

Thank you for your help.

Your code is incomplete.

1 Like

Can you tell me what is missing?
I am not an expirienced programmer

It's missing a bunch of variable definitions, and a setup and loop function.

Why are you using Serial1.write?

Post the whole code. Posting snippets leaves out important information.

1 Like

regarding the setup and loop functions, I have this "void System::Laser_Output_testing" running in the loop. the code was too big for me to post here.

main.cpp

#include <Arduino.h>
#include <PID_v1.h>
#include <LiquidCrystal.h>

#include <system.h>
#include <UserInterface.h>

System sys;
UserInterface UI;

//################################### Laser PID #################################
//###############################################################################
double Setpoint; //target value
double Input;    //Temperature sensor (pyrometer)
double Output;   //ouput value of the PID controller
//PID parameters:
double Kp = 0.1, Ki = 6, Kd = 0;
//Laser PID
PID laserPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

void setup()
{
  Serial1.begin(baudRate_1); //Serial 1 = Laser Serial Communication (RS232)

  //Initialize Pyrometer & Laser
  sys.Init_Pyrometer();  //initialize Pyrometer
  sys.Init_LaserStart(); //initialize Laser PIN
  sys.Init_PF();         //initialize Powder Feeder

  //Initialize UI
  UI.BeginConfig(); //Begining Configurations

  //Laser PID Setup
  Input = 0;                         //Tempreature Reading Value ("TR") [ºC]. Defined by Pyrometer input values.
  Setpoint = 0;                      //Temperature Target Value ("TT") [ºC]. Defined in "UI".
  laserPID.SetMode(AUTOMATIC);       //Turn PID ON
  laserPID.SetTunings(Kp, Ki, Kd);   //Set defined Kp, Ki and Kd
  laserPID.SetSampleTime(10);        //Sample time = 10 [ms]
  laserPID.SetOutputLimits(10, 100); //Output limits = Diode Current (10-100% of Max Laser Power)
}

void loop()
{
  //UI Configurations Start (Running Once)
  UI.Config();              //UI request for desired Target Temperature ("TT") and Mass Flow Rate ("MFR").
  Setpoint = UI.TempTarget; //PID Setpoint, user desired value "TT".

  UI.Laser_ON();       //UI intruction to user requesting laser start.
  sys.Laser_InitCOM(); //Establish initial communications to laser. Check "system.cpp".

  UI.PF_Config();   //User Configurations ("TT" and "MFR")
  sys.PF_CompRPM(); //Compute Powder Feeder RPM%
  UI.PF_Purge();    //Powder Feeder Purge

  UI.Ready2Print(); //Processing Ready to Deposit

  if (UI.Ready == true)
  {
    //temperature reading [ºC]
    sys.TempReading();         //Recieve Pyrometer Readings
    Input = sys.TempReading(); //Tempreature Reading Value ("TR") [ºC]. Defined by Pyrometer input values.

    //PID Computation
    laserPID.Compute(); //PID Output Computation

    //Laser Output
    //sys.Laser_Output(Output); //Laser Output Instructions (Serial Communication, RS232)
    sys.Laser_Output_testing();

    //Powder Feeder Control
    sys.PF_CompRPM(); //Compute RPM% that the PF requires to turn at the desired MFR
    sys.PF_Output();  //Output RPM% to Powder Feeder

    //Display Temperatures (Target & Read) and Mass Flow Rate on the LCD
    UI.ProcessingDisplay(Output);
  }

  //SAFE function to test laser communication
  //sys.laser_testing();
}

system.cpp

#include <system.h>
#include <LiquidCrystal.h>
#include <UserInterface.h>

UserInterface UIsys;

//############################################## SETUP FUNCTIONS ##############################################
//#############################################################################################################

//############################################# INITIALIZE PINS #############################################
void System::Init_LaserStart()
{
    pinMode(LaserStart_IN, INPUT); //Start laser pin (ON/OFF INPUT pin)
}

void System::Init_Pyrometer()
{
    pinMode(Pyrometer_IN, INPUT); //pyrometer pin is INPUT
}

void System::Init_PF()
{
    pinMode(D1_rpm_OUT, OUTPUT);
    pinMode(D2_rpm_OUT, OUTPUT);
}

//############################################## LOOP FUNCTIONS ##############################################
//############################################################################################################

//###################################### TEMPERATURE READINGS FUNCTIONS ######################################
double System::TempReading()
{
    Temp_Reading_V = analogRead(Pyrometer_IN);                  //Temperature read by pyrometer
    Temp_Reading_C = map(Temp_Reading_V, 205, 1023, 600, 2300); //Voltage to [ºC] conversion. Pyrometer Range = 600 to 2300 [ºC]

    return Temp_Reading_C;
}

//############################################# LASER  FUNCTIONS #############################################

void System::Laser_InitCOM()
{

    if (InitCOM == false)
    {

        if (Serial1.available())
        {
            char laser_DMOD[32] = "EMOD";
            Serial1.write(laser_DMOD); // Enable Modulation
            Serial1.write('\r');
            Serial1.write('\n');
        }

        if (Serial1.available())
        {
            char laser_DEC[32] = "DEC";
            Serial1.write(laser_DEC); // Disable External Control
            Serial1.write('\r');
            Serial1.write('\n');
        }

        if (Serial1.available())
        {
            char laser_ELE[32] = "DLE";
            Serial1.write(laser_ELE); // Disable Hardware Emission Control
            Serial1.write('\r');
            Serial1.write('\n');
        }

        if (Serial1.available())
        {
            char laser_EMON[32] = "EMON";
            Serial1.write(laser_EMON); // Emission ON
            Serial1.write('\r');
            Serial1.write('\n');
        }

        InitCOM = true;
    }
}

void System::Laser_Output(double input)
{

    duration = pulseIn(LaserStart_IN, HIGH, 1100); //How long is laserStart_pin HIGH (HIGH = laser emission OFF)

    if (duration <= 1000 && duration != 0) //Laser ON
    {

        if (Serial1.available())
        {
            char laser_SDC[32] = "SDC "; // Set Diode Current.
            char laser_PID_input[32];
            itoa(input, laser_PID_input, 10);
            Serial1.write(laser_SDC);
            Serial1.write(laser_PID_input); //PID_value = Diode Current (10-100% of Max Laser Power)
            Serial1.write('\r');
            Serial1.write('\n');

            //Debug Serial Communication:
            // UIsys.debugSDC(laser_SDC, laser_PID_input);
        }
    }

    if (duration == 0 || duration > 1000) //Laser OFF
    {
        if (Serial1.available())
        {
            char laser_SDC0[32] = "SDC 0"; // Set Diode Current to 0% (OFF).
            Serial1.write(laser_SDC0);
            Serial1.write('\r');
            Serial1.write('\n');

            //Debug Serial Communication:
            // char laser_SDC000[32] = "00";
            // UIsys.debugSDC(laser_SDC0, laser_SDC000);
        }
    }
}

void System::Laser_Output_testing()
{
    duration = pulseIn(LaserStart_IN, HIGH, 1100); //How long is laserStart_pin HIGH (HIGH = laser emission OFF)

    if (duration <= 1000 && duration != 0) //Laser ON
    {

        if (Serial1.available())
        {
            char laser_ABN[32] = "ABN";
            Serial1.write(laser_ABN); // Guide laser ON
            Serial1.write('\r');
            Serial1.write('\n');
        }
    }

    if (duration == 0 || duration > 1000) //Laser OFF
    {
        if (Serial1.available())
        {
            char laser_ABF[32] = "ABF";
            Serial1.write(laser_ABF); // Guide laser OFF
            Serial1.write('\r');
            Serial1.write('\n');
        }
    }
}

//Laser Testing
void System::laser_testing() //Laser comunication testing code (SAFE)
{
    if (Serial1.available())
    {
        char laser_ABN[32] = "ABN";
        Serial1.write(laser_ABN); // Guide laser ON
        Serial1.write('\r');
        Serial1.write('\n');
    }

    delay(1000);

    if (Serial1.available())
    {
        char laser_ABF[32] = "ABF";
        Serial1.write(laser_ABF); // Guide laser OFF
        Serial1.write('\r');
        Serial1.write('\n');
    }

    delay(1000);
}

//############################################# POWDER FEEDER  FUNCTIONS #############################################

void System::PF_CompRPM()
{
    //rpm_perc = UIsys.MFRTarget; //Percentagem de RPM em função do Mass Flow Rate
    rpm_perc = 20; //testing

    rpm_1 = map(rpm_perc, 0, 100, 0, 255);
    rpm_2 = map(rpm_perc, 0, 100, 0, 255);
}

void System::PF_Output()
{

    if (UIsys.D1start == true) //Disk 1 ON
    {
        analogWrite(D1_rpm_OUT, rpm_1);
    }

    if (UIsys.D2start == true) //Disk 2 ON
    {
        analogWrite(D2_rpm_OUT, rpm_2);
    }

    if (UIsys.D1start == false) //Disk 1 OFF
    {
        analogWrite(D1_rpm_OUT, 0);
    }

    if (UIsys.D2start == false) //Disk 2 OFF
    {

        analogWrite(D2_rpm_OUT, 0);
    }
}

void System::PF_PurgeOutput()
{

    if (UIsys.D1start == true) //Disk 1 ON
    {
        analogWrite(D1_rpm_OUT, rpm_1);
    }

    if (UIsys.D2start == true) //Disk 2 ON
    {
        analogWrite(D2_rpm_OUT, rpm_2);
    }

    if (UIsys.D1start == false) //Disk 1 OFF
    {
        analogWrite(D1_rpm_OUT, 0);
    }

    if (UIsys.D2start == false) //Disk 2 OFF
    {

        analogWrite(D2_rpm_OUT, 0);
    }
}

system.h

#ifndef _system_
#define _system_

#include <Arduino.h>
#include <LiquidCrystal.h>
#include <UserInterface.h>

class System
{
private:
#define baudRate_1 57600

public:
    //Pins:
    const int Pyrometer_IN = A12; //Pyrometer IN
    const int LaserStart_IN = 35; //Communication from RAMPS GCode (START/STOP Processing/extruding)
    const int Start_pin = 50;     //Communication from RAMPS (deposition started = HIGH; depsition STOPED/ENDED == LOW)
    //Powder Feeder Pins:
    const int D1_rpm_OUT = 46; //Output Disk 1 Rotation
    const int D2_rpm_OUT = 44; //Output Disk 2 Rotation

    //##################################  SETUP  ####################################
    //###############################################################################
    void Init_Pyrometer(); //Initialize Pyrometer Readings Pin

    void Init_LaserStart(); //Initialize RAMPS-Laser Communication Pin

    void Init_PF(); //Initialize Powder Feeder Output Pins

    //##################################  LOOP  #####################################
    //###############################################################################

    //##########################  TEMPERATURE READINGS  #############################
    //pyrometer functions (check "system.cpp"):
    double TempReading();

    //temperature variables/constants:
    int Temp_Reading_V = 0;    //temperature read by Pyrometer in [Volts]
    double Temp_Reading_C = 0; //temperature read by Pyrometer in [ºC]

    //################################   LASER   ####################################
    //Initialize Laser Serial Communication
    void Laser_InitCOM();    //Laser Initial Serial Communication (RS232). To run once.
    boolean InitCOM = false; //Initial COM Flag

    //laser functions (check "system.cpp"):
    void Laser_Output(double input); //Laser Output Instructions
    void Laser_Output_testing();

    int duration = 0;

    //################################   POWDER FEEDER   ############################
    int rpm_1;
    int rpm_2;
    int rpm_perc;

    void PF_CompRPM(); //Compute Powder Feeder RPM%
    void PF_Output();  //Output RPM% to Powder Feeder

    void PF_PurgeOutput(); //Used in "UserInterface.cpp"
    int PurgeDuration = 1500;

    ////##################################  TESTING  ################################
    //###############################################################################
    void laser_testing(); //SAFE code to test laser SERIAL COMS
};

#endif

If you want I can post the UI part of the code, but i think it is not relevant. The loop is running, I can see the temperature reading changing, so it is running well. It is just that first function I posted in the beginning of the thread that is not working

btw, the code is compiling successfully.

@TheMemberFormerlyKnownAsAWOL @groundFungus any ideia of what could be wrong?
Did I post too much code now?

Why does there have to be data available on serial1 before you can send a command to laser?

actually it does not. but it worked before. should I be using availableForWrite?
I just want to check if I can send data

I would just comment it out and try it.

1 Like

still not working

You have the same thing throughout your code. Perhaps one of the precursor commands is important.

I recall that you got some code talking to the laser earlier. Do you have some simpler code to test the commincations?

This is the simplest/safer instruction to test the laser. I do not think the problem is because of the serial communication, what I think the problem is, is that the pulseIn is not reading the pulses correctly or maybe not even reading the pulses.

Or, most likely, my "If" cycle is wrong. I just cannot see the issue.

The serial communication as been tested many (and I mean MANY :sweat_smile:) times before, and it is working fine.

Maybe add some serial prints to that function.

1 Like

What does your signal look like? The pulseIn() function will return 0 if the signal doesn't go from LOW to HIGH and HIGH to LOW within 1.1 milliseconds and if it DOESN'T return 0 you ignore any pulse less than a millisecond.