Skocz do zawartości

[Atmega328P] Problem z PWM na OC1A


Heniek

Pomocna odpowiedź

Cześć,
tworzę prosty program, który odbiera dane z BT i steruje silnikami poprzez mostki L9110. Problem polega na tym, że o ile na pinie 12 PWM działa tak jak zakładam, o tyle na pinie 15 kompletnie to nie działa. Nie wiem czy dobrze wyczytałem, ale OC1 działa na timerze 16-bitowym, a OC0 na 8-bitowym. Czy to jest ta różnica? Da się to jakoś zmienić, ustawić?

Kod piszę w Arduino IDE, ale wgrywam .hex przez USBASP.

Zauważyłem, że PWM na tym pinie 15 (9) działa na płytce Arduino, ale po wyjęciu Atmegi do własnego układu przestaje działać.

Edytowano przez Heniek
Link do komentarza
Share on other sites

@Heniek witam na forum 🙂 Pokaż kod swojego programu, bo inaczej ciężko coś doradzić.

13 godzin temu, Heniek napisał:

Zauważyłem, że PWM na tym pinie 15 (9) działa na płytce Arduino, ale po wyjęciu Atmegi do własnego układu przestaje działać.

Nic takiego nie powinno mieć miejsca. Mikrokontroler musi działać tak samo, gdy jest wyciągnięty z Arduino - no chyba, że podłączyłeś zły rezonator kwarcowy?

Link do komentarza
Share on other sites

(edytowany)
#include <SoftwareSerial.h>
#include <Servo.h>

#define ENG_L_DIR 7  //13
#define ENG_L_PWM 6  //12

#define ENG_R_DIR 8   //14
#define ENG_R_PWM 9   //15

#define ENG_W_DIR 10  //16
#define ENG_W_PWM 11  //17

#define FIRE_ACT 12   //18
#define GUN_PIN 13    //19

#define GUN_MAX 80
#define GUN_MIN 60

SoftwareSerial BT(2, 3); //RX, TX

Servo Gun;
int GUN_POS = 70;

void setup()
{
  
  BT.begin(9600);
  //Serial.begin(9600);

  Gun.attach(GUN_PIN);

  pinMode(ENG_L_DIR, OUTPUT);
  pinMode(ENG_L_PWM, OUTPUT);
  pinMode(ENG_R_DIR, OUTPUT);
  pinMode(ENG_R_PWM, OUTPUT);
  pinMode(ENG_W_DIR, OUTPUT);
  pinMode(ENG_W_PWM, OUTPUT);
  pinMode(FIRE_ACT, OUTPUT);

  digitalWrite(ENG_L_DIR, LOW);
  digitalWrite(ENG_R_DIR, LOW);
  digitalWrite(ENG_W_DIR, LOW);
  digitalWrite(FIRE_ACT, LOW);

  analogWrite(ENG_L_PWM, LOW);
  analogWrite(ENG_R_PWM, LOW);
  analogWrite(ENG_W_PWM, LOW);
}

char dir, cvalue;
int value, pwm;

void loop()
{
  if (BT.available() != 0) {

    if (dir == 'x' || dir == 'y' || dir == 'w' || dir == 'g'
      || dir == 'l' || dir == 'r') {
      cvalue = BT.read();
      //Serial.print("Read value ");
      //Serial.println(cvalue);
      value = cvalue - '0';

      switch (value)
      {
        case 6:
        case 4:
          pwm = 64; //25%
          break;
        case 7:
        case 3:
          pwm = 128; //50%
          break;
        case 8:
        case 2:
          pwm = 192; //75%
          break;
        case 9:
        case 1:
          pwm = 255; //100%
          break;
        default:
          pwm = 0; // stop
          break;
      }

      BT.print(dir); BT.println(value);
      BT.println(pwm);

      switch (dir)
      {
        case 'l':
          if (value > 5) {
            analogWrite(ENG_L_PWM, 0);
            digitalWrite(ENG_L_DIR, HIGH);
            analogWrite(ENG_L_PWM, 255 - pwm);
          }
          else if (value < 5) {
            analogWrite(ENG_L_PWM, 0);
            digitalWrite(ENG_L_DIR, LOW);
            analogWrite(ENG_L_PWM, pwm);
          }
          else { // stop
            analogWrite(ENG_L_PWM, 0);
            digitalWrite(ENG_L_DIR, LOW);
          }
          //Serial.println("l " + value);
          break;
        case 'r':
          if (value > 5) {
            analogWrite(ENG_R_PWM, 0);
            digitalWrite(ENG_R_DIR, HIGH);
            analogWrite(ENG_R_PWM, 255 - pwm);
          }
          else if (value < 5) {
            analogWrite(ENG_R_PWM, 0);
            digitalWrite(ENG_R_DIR, LOW);
            analogWrite(ENG_R_PWM, pwm);
          }
          else { // stop
            analogWrite(ENG_R_PWM, 0);
            digitalWrite(ENG_R_DIR, LOW);
          }
          //Serial.println("r " + value);
          break;
        case 'x':
          if (value > 5) { // right
            analogWrite(ENG_R_PWM, 0);
            digitalWrite(ENG_R_DIR, LOW);
            digitalWrite(ENG_L_DIR, HIGH);
            analogWrite(ENG_L_PWM, 255 - pwm);
          }
          else if (value < 5) { // left
            analogWrite(ENG_L_PWM, 0);
            digitalWrite(ENG_L_DIR, LOW);
            digitalWrite(ENG_R_DIR, HIGH);
            analogWrite(ENG_R_PWM, 255 - pwm);
          }
          else { // stop
            analogWrite(ENG_L_PWM, 0);
            analogWrite(ENG_R_PWM, 0);
            digitalWrite(ENG_R_DIR, LOW);
            digitalWrite(ENG_L_DIR, LOW);
          }
          //Serial.println("x " + value);
          break;
        case 'y':
          if (value > 5) {
            digitalWrite(ENG_R_DIR, HIGH);
            digitalWrite(ENG_L_DIR, HIGH);
            analogWrite(ENG_R_PWM, 255 - pwm);
            analogWrite(ENG_L_PWM, 255 - pwm);
          }
          else if (value < 5) {
            digitalWrite(ENG_R_DIR, LOW);
            digitalWrite(ENG_L_DIR, LOW);
            analogWrite(ENG_R_PWM, pwm);
            analogWrite(ENG_L_PWM, pwm);
          }
          else { // stop
            analogWrite(ENG_L_PWM, 0);
            analogWrite(ENG_R_PWM, 0);
            digitalWrite(ENG_R_DIR, LOW);
            digitalWrite(ENG_L_DIR, LOW);
          }
          //Serial.println("y " + value);
          break;
        case 'w':
          if (value > 5) {
            digitalWrite(ENG_W_DIR, LOW);
            digitalWrite(ENG_W_PWM, pwm);
          }
          else if (value < 5) {
            digitalWrite(ENG_W_DIR, HIGH);
            digitalWrite(ENG_W_PWM, 255 - pwm);
          }
          else { // stop
            digitalWrite(ENG_W_DIR, LOW);
            digitalWrite(ENG_W_PWM, 0);
          }
          //Serial.println("w " + value);
          break;
        case 'g':
          if(value > 0 && value < 10) {
            value = value + 1;
            value = (GUN_MAX - GUN_MIN)*value/10;
            GUN_POS = GUN_MIN + value;
            Gun.write(GUN_POS);
          }
          //Serial.println("g " + value);
          break;
      }

      dir = 'z';
    }
    else if (dir == 'f') {
      //Serial.println("Fire");
      digitalWrite(FIRE_ACT, HIGH);
      delay(500);
      digitalWrite(FIRE_ACT, LOW);
      dir = 'z';
      //Serial.println("f ");
    }
    else {
      dir = BT.read();
      //Serial.print("Read dir ");
      //Serial.println(dir);
    }
  }
}

Wysyłam znak + cyfra z zakresu 1 - 5.
Podpięty rezonator 16MHz przez dwa kondensatory 22pF do masy.

//Chyba jednak nie działa na płytce też. Już się pogubiłem o co tutaj chodzi 😂 PWM na 6(12) działa po przepięciu na 9(15) nie działa.

//Prosty kod, w którym ustawiam w setup() na sztywno pwm na 9 działa, ale w tym moim programiku nie działa. Nie mam już pomysłów, pwm wylicza dobrze.

//Winowajcą jest Gun.attach(GUN_PIN); Ta linijka powoduje, że PWM na pinie 9 wariuje. Da się coś z tym zrobić?

Edytowano przez Heniek
Link do komentarza
Share on other sites

@Heniek to nie jest błąd - tak ma być, tzn. jest to zgodne z dokumentacją Arduino: https://www.arduino.cc/en/reference/servo

Cytat

On boards other than the Mega, use of the library disables analogWrite() (PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins. 

Korzystanie z biblioteki Servo uniemożliwia korzystanie z PWM na pinach 9 i 10.

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Już sobie z tym poradziłem. Przepiąłem pod inne piny DC, a serwo wpiąłem pod 9. Dzięki!

A da się jakoś zaradzić na drgające serwo? Chodzi o to, że gdy czasem steruje silnikami (PWM) lub zapalam diodę, serwomechanizm potrafi zadrgać.
Zasilanie dla Atmega i diody jest przez stabilizator L7805ABV. Serwomechanizm ma zasilanie z drugiego stabilizatora L7805ABV, a sterowniki silników i stabilizator są wpięte do pakietu 7.4V 2500mAh. Oczywiście za stabilizatorami jest kondensator 100nF, a przed Atmegą dodatkowo 100uF.

Link do komentarza
Share on other sites

@Heniek w takim razie masz tam cały czas jakieś problemy z zasilaniem. Najlepiej będzie, jeśli dodasz jeszcze jakiś kondensatory w okolicy serwa. Spróbuj wstawić 100-220 uF i zobacz czy nie będzie widocznej poprawy.

Link do komentarza
Share on other sites

(edytowany)

Włożyłem dwa 100uF równolegle i nie dało za wiele 😕
A czy to może być za słabe źródło?
Posiadam akumulator litowo-polimerowy 7.4V 2000mAh 25C od drona Syma.

Edytowano przez Heniek
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.