• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Odświeżanie ekranu
#1
Witam 

Mam problem mianowicie chodzi o to że po włączeniu silnika krokowego zamraża się ekran co jest nie tak coś z timereami ? 

Pozdrawiam

#include <PID_v1_bc.h>
#include <thermistor.h>                    
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Arduino.h>

#define SCREEN_WIDTH 128                    
#define SCREEN_HEIGHT 64                    

#define OLED_RESET    -1                  
#define SCREEN_ADDRESS 0x3C                  
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define initialTemp 180               
#define minTemp 180                     
#define maxTemp 230
#define initialSpeed 10
#define minSpeed 1
#define maxSpeed 50
#define initialMot 0
#define minMot 0
#define maxMot 2



int encLowLim = minTemp;                   
int encHighLim = maxTemp;
int encIncrement = 1;
int encCurrent = initialTemp;
int dataInputNo = 0;                        

static int pinA = 2;                        
static int pinB = 3;                        
volatile int encoderPos = initialTemp;      
volatile int prevEncoderPos = initialTemp;  

byte oldButtonState = HIGH;                
const unsigned long debounceTime = 10;      
unsigned long buttonPressTime;              
boolean pressed = false;

const int temperaturePin = A0;              
const int pwmPin = 5;
const int enablePin = 8;
const int motDirPin = 4;
const int motStepPin = 9;
const int encButton = 12;


int loopTime = 500;                          
unsigned long currentTime = 0;

double Kp = 80.0;                            
double Ki = 35.0;
double Kd = 80.0;

thermistor therm1(temperaturePin,0);        

double setpoint = initialTemp;              
double input, output;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

int motSpeed = initialSpeed;                
int motDir = initialMot;
int motMaxDelay = 100;
int motDelayTime = 500;

void setup()
{
  Serial.begin(9600);
    pinMode(6, OUTPUT);
    digitalWrite(6, HIGH);                                    

  //SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;Wink; // Don't proceed, loop forever
  }

  display.clearDisplay();                               
 
  pinMode(pwmPin, OUTPUT);                                
 
  pid.SetMode(AUTOMATIC);                               
  pid.SetOutputLimits(0, 255);

  input = therm1.analog2temp();                         
 
  pinMode(pinA, INPUT);                            
  pinMode(pinB, INPUT);                           
  attachInterrupt(digitalPinToInterrupt(pinA), rotaryInterrupt, CHANGE);
  attachInterrupt(digitalPinToInterrupt(pinB), rotaryInterrupt, CHANGE);
  pinMode(encButton, INPUT_PULLUP);                      
  pinMode(motDirPin, OUTPUT);                           
  pinMode(motStepPin, OUTPUT);
  digitalWrite(motDirPin, HIGH);                          

  Serial.println("Setup complete");                    
}

void loop()
{
  
  currentTime = millis();

  
  input = therm1.analog2temp(); 
 
 
  pid.Compute();
 
  
  analogWrite(pwmPin, output);
  int temp = input;
 
  
  Serial.print("Temperature: ");
  Serial.print(temp);
  Serial.print(" \u00B0C");
  Serial.print("\tPWM Output: ");
  Serial.print(output);
  Serial.print("\tEncoder: ");
  Serial.println(encCurrent);

  
  updateDataDisplay ();

  
  while(millis() < currentTime + loopTime)
  {
    byte buttonState = digitalRead (encButton);
    if (buttonState != oldButtonState)
    {
      Serial.println("Button change");
      if (millis () - buttonPressTime >= debounceTime)      
      {
        buttonPressTime = millis ();                        
        oldButtonState =  buttonState;                  
        if (buttonState == LOW)
        {
          pressed = true;
          Serial.println("Button Pressed");
        }
        else
        {
          if (pressed == true)                             
          {
            boolean pressed = false;
            Serial.println("Button Released");
            if (dataInputNo == 0)                          
            {
              dataInputNo = 1;
              encCurrent = motSpeed;
              encLowLim = minSpeed;
              encHighLim = maxSpeed;
            }
            else if (dataInputNo == 1)
            {
              dataInputNo = 2;
              encCurrent = motDir;
              encLowLim = minMot;
              encHighLim = maxMot;
            }
            else
            {
              dataInputNo = 0;
              encCurrent = setpoint;
              encLowLim = minTemp;
              encHighLim = maxTemp;
            }
          }
        } 
      }
    }

    //Set the parameter being edited equal to the current encoder position
    if (dataInputNo == 0)                                   
    {
      setpoint = encCurrent;
    }
    else if (dataInputNo == 1)
    {
      motSpeed = encCurrent;
      motDelayTime = 100 * (1 + maxSpeed - motSpeed);
    }
    else
    {
      motDir = encCurrent;
    }

    //Set the motor direction
    if (motDir == 0)
    {
      pinMode(enablePin, OUTPUT);                
      digitalWrite(motDirPin, LOW);             
      updateDataDisplay ();
    }
    else if (motDir == 2)
    {
      pinMode(enablePin, OUTPUT);                 
      digitalWrite(motDirPin, HIGH);                
      updateDataDisplay ();
    }
    else
    {
      pinMode(enablePin, INPUT);                   
    }
   
    //Pulse the stepper motor if forward or reverse is selected
    while (motDir != 1)
    {
      runMotor ();
      motDir = encCurrent;
    }
  }
}

//Increment the current setting if the rotary encoder is turned
void rotaryInterrupt ()
{
  encoderPos = digitalRead(pinA);
  if ((prevEncoderPos == 0) && (encoderPos == 1))
  {
      if (digitalRead(pinB) == 1)
      {
        if (encCurrent < encHighLim)
          encCurrent=encCurrent+encIncrement;              
      }
      else
      {
        if (encCurrent > encLowLim)
          encCurrent=encCurrent-encIncrement;              
      }
  }
  prevEncoderPos = encoderPos;
  delay(1);
}

//Update the OLED display contents
void updateDataDisplay ()
{
  display.clearDisplay();                                  
  display.setTextSize(1);                                  
  display.setTextColor(SSD1306_WHITE);                     
  display.setCursor(2,10);                                  
  display.print(F("Aktualna Temp: "));                      
  display.setCursor(2,20);
  display.print(F("Zadana Temp: "));
  display.setCursor(2,30);
  display.print(F("Predkosc : "));
  display.setCursor(2,40);
  display.print(F("Silnik: "));
  int temp = input;
  int setPointInt = setpoint;
  int selected = 0;
  if (dataInputNo == 0)                                    
  {
    selected = 20;
  }
  else if (dataInputNo == 1)
  {
    selected = 30;
  }
  else
  {
    selected = 40;
  }
  display.setCursor(87,selected);                            
  display.print(F(">"));
  display.setCursor(97,10);
  display.print(temp);
  display.print(F("C"));
  display.setCursor(97,20);
  display.print(setPointInt);
  display.print(F("C"));
  display.setCursor(97,30);
  display.print(motSpeed);
  display.setCursor(97,40);
  if (motDir == 0)
    display.print(F("TYL"));
  else if (motDir == 2)
    display.print(F("PRZOD"));
  else
    display.print(F("WYL"));
  display.display();                                          
}

//Turn the reel motor and maintain hot end temperature
void runMotor ()
{
  digitalWrite(motStepPin, HIGH);
  delayMicroseconds(motDelayTime);
  digitalWrite(motStepPin, LOW);
  if(millis() < currentTime + loopTime)
  {
    delayMicroseconds(motDelayTime);
  }
  else
  {
    //Record the start time for the loop
    currentTime = millis();

    //Read the temperature
    input = therm1.analog2temp(); 
 
    //Compute the PID output
    pid.Compute();
 
    //Update the PWM output
    analogWrite(pwmPin, output);
  }
}
 
Odpowiedź
#2
Pid cie blokuję raczej, sprawdź to
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#3
(19-04-2024, 14:21)Jarewa0606 napisał(a): Pid cie blokuję raczej,  sprawdź to
Chyba nie bo pid działa cały czas, blokada jest tylko po załączeniu silnika
 
Odpowiedź
#4
Nie napisałeś jaka to płytka. W UNO nie ma double, liczy i tak na float, za to wolniej niż w tańszym ESP.
while(millis() < currentTime + loopTime) - znajdz inny sposob.
Jak zamierzasz w każdym wywołaniu pętli loop coś drukować, i jeszcze coś z tego zrozumieć.... to po prostu już użyj delay.
Podziel sobie sekundę na określoną ilość, tu np. proponuję na 100, w każdej sprawdzaj przycisk, możesz użyć bibliotek easyButton, oneButton, accelstepper, ekran odświeżaj nie częściej niż co 10 jednostek, millis wystarczy raz odczytać na początku loop, jak masz tak długi loop, to i tak nie ma znaczenia.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#5
Płytka Nano ale już próbowałem. Na symulatorze i ciągle ro. Samo po włączeniu silnika wyświetlacz zatrzymuje się w lini silnika i koniec
 
Odpowiedź
#6
Bo każesz czekać

while (motDir != 1)
{
runMotor ();
motDir = encCurrent;
}

Nie sprawdzałem dokładnie bo ja tego nie pisałem, ale ta funkcja blokuje wyświetlacz i działa tylko silnik i enkoder. Wiec dopiero jak zakończy sie pętla while czyli co tam ustawisz enkoderem to dopiero puści i wyświetlacz sie uaktywni ale to musi być spełniony warunek encCurrent =1 i pochodzi z przerwań enkodera tego nie analizowałem.

Po drugie
void rotaryInterrupt ()
{
encoderPos = digitalRead(pinA);
if ((prevEncoderPos == 0) && (encoderPos == 1))
{
if (digitalRead(pinB) == 1)
{
if (encCurrent < encHighLim)
encCurrent=encCurrent+encIncrement;
}
else
{
if (encCurrent > encLowLim)
encCurrent=encCurrent-encIncrement;
}
}
prevEncoderPos = encoderPos;
delay(1);
}

Zabrakło przy tej zmiennej bardzo ważnego przyrostka jak "volatile" skoro jest obliczana na przerwaniach.

int encCurrent = initialTemp;


Ten program ma bardzo poważne błędy jak i nie jest przemyślany. A działa tak jak zostało napisane.
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#7
To chyba sobie nie poradzę aż takim magikiem nie jestem ogólnie potrzebuje bardzo dobrego pid do grzania grzałki i ten mi tu się sprawdza idealnie do tego potrzebuje opcje właczenia silnika krokowego + regulacja obrotów niby prosty program a jednak przerosło mnie ?
 
Odpowiedź
#8
Nie pisałeś tego programu dlatego cię przerosło i nie rozumiesz a próbujesz skleić kilka małych a bez wiedzy rozumowania jak to działa jesteś w kropce.
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#9
Dokładnie tak trudno trzeba szukać innej bazy
 
Odpowiedź
#10
nie bazy bo to nic nie da musisz sam nauczyć się, bo inaczej jesteś skazany na to co ktoś napisał, a ten program pewnie idzie poprawić tylko trzeba go zrozumieć popracować nad nim
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości