Belajar Elektro

Random post

Belajar Elektro

Powered By Blogger

Thursday, 12 June 2025

KODE UCAPAN TERIMAKASIH

 DIY SWR & POWER METER VHF 500 WATT 2N











KODE PROGRAM UCAPAN TERIMAKASIH :

#include <U8g2lib.h>

#include <Wire.h>

 

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);

 

const int buzzerPin = 4;

 

unsigned long lastChange = 0;

unsigned long lastMove = 0;

const unsigned long moveInterval = 150;

 

int stage = 0;

int pupilX = 0;

int pupilDir = 1;

const int maxPupilOffset = 6;

 

unsigned long stageDurations[] = {3000, 2000, 2000, 5000}; // durasi tiap stage

 

int planeX = -40;

int planeY = 28;

 

bool propellerToggle = false;  // animasi baling-baling

 

// Awan Layer 1 (jauh)

const int cloudCount1 = 2;

int cloudX1[cloudCount1] = {130, 200};

int cloudY1[cloudCount1] = {10, 18};

 

// Awan Layer 2 (dekat)

const int cloudCount2 = 2;

int cloudX2[cloudCount2] = {160, 220};

int cloudY2[cloudCount2] = {25, 32};

 

void setup() {

  pinMode(buzzerPin, OUTPUT);

  u8g2.begin();

  u8g2.setFont(u8g2_font_ncenB14_tr);

}

 

void loop() {

  unsigned long now = millis();

 

  // Update animasi mata saat stage 0

  if (stage == 0) {

    if (now - lastMove > moveInterval) {

      pupilX += pupilDir;

      if (pupilX > maxPupilOffset || pupilX < -maxPupilOffset) {

        pupilDir = -pupilDir;

        pupilX += pupilDir * 2;

      }

      lastMove = now;

    }

  }

 

  // Update animasi pesawat & awan saat stage 3

  if (stage == 3 && now - lastMove > moveInterval) {

    planeX += 2;

    if (planeX > 128) planeX = -40;

    lastMove = now;

    propellerToggle = !propellerToggle;

 

    // Gerak awan layer 1 (lebih lambat)

    for (int i = 0; i < cloudCount1; i++) {

      cloudX1[i] -= 1;

      if (cloudX1[i] < -30) cloudX1[i] = 130 + random(20);

    }

 

    // Gerak awan layer 2 (lebih cepat)

    for (int i = 0; i < cloudCount2; i++) {

      cloudX2[i] -= 2;

      if (cloudX2[i] < -30) cloudX2[i] = 130 + random(30);

    }

  }

 

  // Ganti stage tiap interval sesuai durasi masing-masing

  if (now - lastChange > stageDurations[stage]) {

    stage = (stage + 1) % 4;

    lastChange = now;

 

    playCallTone(stage);

  }

 

  u8g2.clearBuffer();

 

  switch (stage) {

    case 0:

      drawRobotHeadWithMouthAndEyes(pupilX);

      break;

 

    case 1:

      drawTextCenteredBold("TERIMAKASIH");

      break;

 

    case 2:

      drawTextTwoLinesBold("ATAS", "ORDERANYA");

      break;

 

    case 3:

      drawPlane(planeX, planeY);

 

      // Gambar awan layer 1 (jauh)

      for (int i = 0; i < cloudCount1; i++) {

        drawCloud(cloudX1[i], cloudY1[i]);

      }

 

      // Gambar awan layer 2 (dekat)

      for (int i = 0; i < cloudCount2; i++) {

        drawCloud(cloudX2[i], cloudY2[i]);

      }

      break;

  }

 

  u8g2.sendBuffer();

}

 

void drawRobotHeadWithMouthAndEyes(int pupilOffsetX) {

  u8g2.drawRFrame(0, 0, 128, 64, 12);

 

  int eyeY = 25;

  int leftEyeX = 40;

  int rightEyeX = 88;

  int eyeWidth = 40;

  int eyeHeight = 28;

 

  u8g2.drawEllipse(leftEyeX, eyeY, eyeWidth / 2, eyeHeight / 2);

  u8g2.drawEllipse(rightEyeX, eyeY, eyeWidth / 2, eyeHeight / 2);

 

  int pupilRadius = 8;

  u8g2.drawDisc(leftEyeX + pupilOffsetX, eyeY, pupilRadius);

  u8g2.drawDisc(rightEyeX + pupilOffsetX, eyeY, pupilRadius);

 

  int mouthX = 32;

  int mouthY = 48;

  int mouthW = 64;

  int mouthH = 12;

  u8g2.drawRBox(mouthX, mouthY, mouthW, mouthH, 5);

  u8g2.drawHLine(mouthX, mouthY + mouthH / 2, mouthW);

}

 

void drawTextCenteredBold(const char* text) {

  u8g2.setFont(u8g2_font_ncenB10_tr);  // font tebal 10 px

  int16_t tw = u8g2.getStrWidth(text);

  u8g2.setCursor((128 - tw) / 2, 30);

  u8g2.print(text);

}

 

void drawTextTwoLinesBold(const char* line1, const char* line2) {

  u8g2.setFont(u8g2_font_ncenB10_tr);

  int16_t tw1 = u8g2.getStrWidth(line1);

  int16_t tw2 = u8g2.getStrWidth(line2);

 

  u8g2.setCursor((128 - tw1) / 2, 20);

  u8g2.print(line1);

 

  u8g2.setCursor((128 - tw2) / 2, 44);

  u8g2.print(line2);

}

 

void drawPlane(int x, int y) {

  // Badan utama

  u8g2.drawBox(x, y, 24, 6);

 

  // Hidung pesawat

  u8g2.drawTriangle(x + 24, y, x + 32, y + 3, x + 24, y + 6);

 

  // Sayap

  u8g2.drawBox(x + 6, y - 6, 6, 6);  // atas

  u8g2.drawBox(x + 6, y + 6, 6, 6);  // bawah

 

  // Ekor horizontal & vertikal

  u8g2.drawBox(x - 4, y + 1, 4, 2); // horizontal

  u8g2.drawBox(x, y - 5, 2, 5);     // vertikal

 

  // Baling-baling animasi

  static bool propellerToggle = false;

  propellerToggle = !propellerToggle;

  if (propellerToggle) {

    u8g2.drawDisc(x + 31, y + 3, 2); // mode bulat

  } else {

    u8g2.drawLine(x + 30, y + 1, x + 32, y + 5); // silang

    u8g2.drawLine(x + 32, y + 1, x + 30, y + 5);

  }

 

  // Asap knalpot

  u8g2.drawTriangle(x - 6, y + 1, x - 4, y - 1, x - 4, y + 5);

}

 

void drawCloud(int x, int y) {

  u8g2.drawCircle(x, y, 6, U8G2_DRAW_ALL);

  u8g2.drawCircle(x + 6, y - 2, 5, U8G2_DRAW_ALL);

  u8g2.drawCircle(x + 12, y, 6, U8G2_DRAW_ALL);

}

 

void playCallTone(int currentStage) {

  int melody0[] = {1000, 1200, 1400, 1200, 1000};

  int melody1[] = {600, 800, 600};

  int melody2[] = {900, 1100, 900};

  int melody3[] = {1300, 1500, 1700};

 

  int duration = 150;

  int* melody;

  int length;

 

  switch (currentStage) {

    case 0:

      melody = melody0;

      length = sizeof(melody0) / sizeof(melody0[0]);

      break;

    case 1:

      melody = melody1;

      length = sizeof(melody1) / sizeof(melody1[0]);

      break;

    case 2:

      melody = melody2;

      length = sizeof(melody2) / sizeof(melody2[0]);

      break;

    case 3:

      melody = melody3;

      length = sizeof(melody3) / sizeof(melody3[0]);

      break;

    default:

      return;

  }

 

  for (int i = 0; i < length; i++) {

    tone(buzzerPin, melody[i], duration);

    delay(duration + 50);

  }

  noTone(buzzerPin);

}


KODE SWR & POWER METER 500 WATT GEN2

KODE DENGAN DEBUG :

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <math.h>

 

// Pengaturan OLED

#define SCREEN_WIDTH 128

#define SCREEN_HEIGHT 64

#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

 

// Pengaturan pin

#define FWD_PIN A0

#define REF_PIN A1

#define ALARM_PIN 4  // Buzzer pasif

 

// Variabel untuk alarm

unsigned long lastAlarmToggle = 0;

bool alarmState = false;

 

// Fungsi konversi tegangan ke daya (dengan rentang terbaru)

float voltageToPower(float voltage) {

  if (voltage <= 0.2) return 1;

  else if (voltage <= 0.4) return 1 + (voltage - 0.2) * (4.0 / 0.2);               // 1–5W

  else if (voltage <= 0.7) return 5 + (voltage - 0.4) * (15.0 / 0.3);              // 5–20W

  else if (voltage <= 1.1) return 20 + (voltage - 0.7) * (30.0 / 0.4);             // 20–50W

  else if (voltage <= 1.2) return 50 + (voltage - 1.1) * (30.0 / 0.1);             // 50–80W

  else if (voltage <= 1.4) return 80 + (voltage - 1.2) * (20.0 / 0.2);             // 80–100W

  else if (voltage <= 1.8) return 100 + (voltage - 1.4) * (50.0 / 0.4);            // 100–150W

  else if (voltage <= 2.2) return 150 + (voltage - 1.8) * (50.0 / 0.4);            // 150–200W

  else if (voltage <= 2.8) return 200 + (voltage - 2.2) * (100.0 / 0.6);           // 200–300W

  else if (voltage <= 3.8) return 300 + (voltage - 2.8) * (100.0 / 1.0);           // 300–400W

  else if (voltage <= 4.2) return 400 + (voltage - 3.8) * (100.0 / 0.4);           // 400–500W

  else return 500;

}

 

// Fungsi smoothing: rata-rata dari beberapa pembacaan analog

float readAveragedAnalog(int pin, int samples = 10) {

  long total = 0;

  for (int i = 0; i < samples; i++) {

    total += analogRead(pin);

    delay(2);  // jeda kecil antar pembacaan

  }

  return (float)total / samples;

}

 

void setup() {

  Serial.begin(9600);

  while (!Serial); // Tunggu hingga port serial siap

  Serial.println(F("Inisialisasi dimulai"));

 

  pinMode(ALARM_PIN, OUTPUT);

  noTone(ALARM_PIN);  // Pastikan buzzer mati

 

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {

    Serial.println(F("OLED gagal!"));

    while (1);

  }

 

  display.clearDisplay();

  display.setTextSize(1);

  display.setTextColor(SSD1306_WHITE);

  display.setCursor(15, 0);

  display.println(F("SWR & POWER METER"));

  display.display();

  delay(2000);

}

 

void loop() {

  float fwdRaw = readAveragedAnalog(FWD_PIN);

  float refRaw = readAveragedAnalog(REF_PIN);

 

  float vFwd = fwdRaw * (5.0 / 1023.0);

  float vRef = refRaw * (5.0 / 1023.0);

 

  float pFwd = voltageToPower(vFwd);

  float pRef = voltageToPower(vRef);

 

  float swr = 1.0;

  if (vFwd > 0.01 && vRef < vFwd) {

    float ratio = vRef / vFwd;

    float sqrtRatio = sqrt(ratio);

    if (sqrtRatio > 0.99) sqrtRatio = 0.99;  // batasi supaya denominator tidak nol

    swr = (1 + sqrtRatio) / (1 - sqrtRatio);

    if (swr > 99) swr = 99;

  }

 

  // Kompensasi SWR agar tidak melonjak drastis pada power besar

  if (pFwd > 20) {  // threshold power 20 watt

    float faktor = 20.0 / pFwd;

    if (faktor < 0.2) faktor = 0.2;  // batas minimal faktor

    swr = 1.0 + (swr - 1.0) * faktor;

  }

 

  float rl = 0;

  if (pFwd > 0.1 && pRef > 0.01) {

    rl = -10.0 * log10(pRef / pFwd);

  } else {

    rl = 99.0;

  }

 

  // Alarm berbunyi jika SWR > 1.5

  if (swr > 1.5) {

    unsigned long currentMillis = millis();

    if (currentMillis - lastAlarmToggle >= 500) { // Alarm berdenyut

      lastAlarmToggle = currentMillis;

      alarmState = !alarmState;

      if (alarmState) {

        tone(ALARM_PIN, 2000);  // Frekuensi 2kHz

      } else {

        noTone(ALARM_PIN);

      }

    }

  } else {

    noTone(ALARM_PIN);

    alarmState = false;

  }

 

  // OLED Tampilkan data

  display.clearDisplay();

 

  display.setCursor(20, 0);

  display.setTextSize(1);

  display.print(F("SWR & POWER METER"));

 

  display.setCursor(0, 12);

  display.setTextSize(1);

  display.print(F("PWR : ")); display.print(pFwd, 1); display.println(F(" W"));

 

  display.setCursor(0, 22);

  display.print(F("REF : ")); display.print(pRef, 1); display.println(F(" W"));

 

  display.setCursor(0, 32);

  display.print(F("SWR : ")); display.println(swr, 2);

 

  display.setCursor(0, 42);

  display.print(F("RL  : ")); display.print(rl, 1); display.println(F(" dB"));

 

  // Bar SWR

  int barWidth = map(swr * 100, 100, 300, 0, 128);

  barWidth = constrain(barWidth, 0, 128);

  display.fillRect(0, 56, barWidth, 6, SSD1306_WHITE);

  display.drawRect(0, 56, 128, 6, SSD1306_WHITE);

 

  display.display();

 

  delay(500);

}

 


0 comments: