Помогите разобраться с ШИМ

Sasha80
Offline
Зарегистрирован: 18.01.2016

Доброго времени суток. Надавно возникла потребность в регулировки яркости диода при помощи шим. Тема эта для меня честно говоря новая, поэтому для начала скачал уже готовый скетч. Собрал схему на основе PT4115 все в принцыпе работает, но питание у меня 12В, а диоды будут 3,5В (3Вт), поэтому нужно чтоб верхняя планка питания ограничивалась именно этой цифрой. ТЕ предел регулировки от 0в до 3,5в. Припоять мощный резистор не предлагайте, мне это не подходит. Вот собственно что поменять в скетче чтоб первый канал ШИМа работал именно в этих пределах. Скетч не секретный, привожу ниже!

#include <Wire.h>
 
#define Sh1 3  // Первый канал ШИМ
#define Sh2 5  // Второй канал ШИМ
#define Rel 7  // Канал управления реле
#define DS3231_I2C_ADDRESS 0x68 // SDA A4, SCL A5
 
int i;                   // переменная цикла
byte MyStep;             // номер в массиве
byte MyStep_old;         // старый номер в массиве
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;  // данные с DS3231
int min_sum;             // минуты с начала дня
int min_sum_ras;         // минуты с начала дня по расписанию 
 
byte minute_old;
 
// Массивы таймеров вкл/выкл
// рабочие дни
// 00:00    Sh1-Off, Sh2-Off,  Rel-Off, dimming1,2 = 0 sec
// 06:15    Sh1-0n,  Sh2-Off,  Rel-Off, dimming1 = 240 sec
// 08:00    Sh1-0n,  Sh2-On,   Rel-Off, dimming2 = 240 sec
// 09:00    Sh1-Off, Sh2-Off,  Rel-On,  dimming = 0 sec
// 12:00    Sh1-0n,  Sh2-0n,   Rel-Off, dimming = 0 sec
// 14:00    Sh1-Off, Sh2-Off,  Rel-On,  dimming = 0 sec
// 21:00    Sh1-0n,  Sh2-On,   Rel-Off, dimming1,2 = 0 sec
// 21:20    Sh1-0n,  Sh2-Off,  Rel-Off, dimming2 = 240 sec
// 21:30    Sh1-Off, Sh2-Off,  Rel-Off, dimming1 = 240 sec
 
// выходные дни
// 00:00    Sh1-Off, Sh2-Off,  Rel-Off, dimming1,2 = 0 sec
// 08:00    Sh1-0n,  Sh2-Off,  Rel-Off, dimming1 = 240 sec
// 08:30    Sh1-0n,  Sh2-On,   Rel-Off, dimming2 = 240 sec
// 09:00    Sh1-Off, Sh2-Off,  Rel-On,  dimming = 0 sec
// 21:00    Sh1-0n,  Sh2-On,   Rel-Off, dimming1,2 = 0 sec
// 21:20    Sh1-0n,  Sh2-Off,  Rel-Off, dimming2 = 240 sec
// 21:30    Sh1-Off, Sh2-Off,  Rel-Off, dimming1 = 240 sec
 
// рабочие дни
byte Hr[9] =   {0,  6, 8, 9, 12, 14, 14, 21, 21};    // часы вкл/выкл
byte Min[9]  = {0, 15, 0, 0,  0,  8,  11, 20, 30};    // минуты вкл/выкл
byte DimT1[9]  = {0, 240, 0, 0, 0, 120, 120, 0, 240};    // время димера первого канала
byte DimT2[9]  = {0, 0, 240, 0, 0, 0, 0, 240, 0};    // время димера второго канала
boolean Sh_K1[9] = {false, true,  true, false, true, false, true,  true,  false};  // состояние первого канала
boolean Sh_K2[9] = {false, false, true, false, true, false, true,  false, false};  // состояние второго канала
boolean Sh_R1[9] = {false, false, false, true, false, true,  false, false, false};  // состояние канала реле
 
// выходные дни
byte Hr_V[7] =   {0, 8, 8,  9, 21, 21, 21};      // часы вкл/выкл
byte Min_V[7]  = {0, 0, 30, 0, 0, 20, 30};       // минуты вкл/выкл
byte DimT1_V[7]  = {0, 240, 0, 0, 0, 0, 240};    // время димера первого канала
byte DimT2_V[7]  = {0, 0, 240, 0, 0, 240, 0};    // время димера второго канала
boolean Sh_K1_V[7] = {false, true,  true, false, true,  true,  false};  // состояние первого канала
boolean Sh_K2_V[7] = {false, false, true, false, true,  false, false};  // состояние второго канала
boolean Sh_R1_V[7] = {false, false, false, true, false, false, false};  // состояние канала реле
 
void setup() {
  Wire.begin(); 
  // инициализация каналов
  pinMode(Sh1, OUTPUT);  
  pinMode(Sh2, OUTPUT);
  pinMode(Rel, OUTPUT);
  analogWrite(Sh1, 0);  
  analogWrite(Sh2, 0);
  digitalWrite(Rel, LOW);
  // сброс первоночальных значений (чтобы при первом обращении к этим переменным сработало обновление по минутам и суткам)
  minute_old = 255;
  MyStep_old = 255;
  MyStep = 0;
  
  //Первоночальная установка времени
  //setDateDs3231(14, 56, 16, 2, 10, 12, 13); //second, minute, hour, dayOfWeek, dayOfMonth, month, year
  
  //----------------------
  // включить для отладки
  Serial.begin(9600);
  //----------------------
}
 
 
//**********************************************
// Основной цикл
void loop()
{
  getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // Читаем время
  if (minute != minute_old)       // изменились минуты 
    {
    //-------------------------------------------------------
    SerialTimeDate();               // включить для отладки
    //-------------------------------------------------------
    min_sum = hour * 60 + minute; // подсчитываем минуты с начала дня
    minute_old = minute;          // сохраняем минуты
    // проверяем расписание
    if (dayOfWeek < 6)            // рабочие дни
      {  
      MyStep = Schedule_Working();
      if (MyStep != MyStep_old)   // изменилось расписание
        {
        digitalWrite(Rel, (Sh_R1[MyStep])? HIGH:LOW); // включаем/выключаем канал реле (Sh_R1[MyStep]==true возвращает HIGH, если истина)
        if (Sh_R1[MyStep] != Sh_R1[MyStep_old]) SerialKanal(3, 0, 0, 0) ;  // включить для отладки
        dimmer1();                // управляем 1 каналом ШИМ
        dimmer2();                // управляем 2 каналом ШИМ
        MyStep_old = MyStep;      // отработали действие в расписании
        }
      }
    else                          // выходные дни
      {
      MyStep = Schedule_Weekend();
      if (MyStep != MyStep_old)   // изменилось расписание
        {
        digitalWrite(Rel, (Sh_R1_V[MyStep])? HIGH:LOW); // включаем/выключаем канал реле (Sh_R1[MyStep]==true возвращает HIGH, если истина)
        if (Sh_R1[MyStep] != Sh_R1[MyStep_old]) SerialKanal(3, 0, 0, 0) ;  // включить для отладки
        dimmer1_V();               // управляем 1 каналом ШИМ
        dimmer2_V();               // управляем 2 каналом ШИМ
        MyStep_old = MyStep;       // отработали действие в расписании
        }
      }
    }
}
// *******************************************************************
byte Schedule_Working(void)
{
for (i = 0; i<9; i++) //опрашиваем массив расписаний
  {
  min_sum_ras = Hr[i] * 60 + Min[i]; // подсчитываем минуты с начала дня по расписанию
  if (min_sum >= min_sum_ras) MyStep = i;
  }
return MyStep;
}
// *******************************************************************
byte Schedule_Weekend(void)
{
for (i = 0; i<7; i++) //опрашиваем массив расписаний
  {
  min_sum_ras = Hr_V[i] * 60 + Min_V[i]; // подсчитываем минуты с начала дня по расписанию
  if (min_sum >= min_sum_ras) MyStep = i;
  }
return MyStep;
}
// *******************************************************************
void dimmer1 (void)      // ШИМ 1 канала (рабочие дни)
{
byte Start_D;            // стартовое значение ШИМ канала
byte Stop_D;             // конечное значение ШИМ канала
int Sleep_D;             // задержка
if (DimT1[MyStep] != 0)  // если нужно плавно включить/выключить ШИМ канал
  {
  Start_D = (Sh_K1[MyStep_old]) ? 60:0; // вычисляем стартовое значение ШИМ канала (предыдущее состояние)
  Stop_D = (Sh_K1[MyStep]) ? 60:0;      // вычисляем конечное значение ШИМ канала (расписание)
  Sleep_D = DimT1[MyStep] * 16.6666;    // вычисляем задержку в мс. 3.9216 = 1000/255
  //--------------------------------------------------------------------
  SerialKanal(1, Start_D, Stop_D, Sleep_D); // включить для отладки
  //--------------------------------------------------------------------
  if (Start_D != Stop_D)                 // если изменилось
    {
    if (Start_D < Stop_D)
      {
      for (i=Start_D; i<Stop_D; i++)     // увеличиваем яркость
          {
          analogWrite(Sh1, i);
          delay (Sleep_D);
          }
      }
    else
      {
      for (i=Start_D; i>Stop_D; i--)     // уменьшаем яркость
          {
          analogWrite(Sh1, i);
          delay (Sleep_D);
          }
      }
    }
  }
digitalWrite(Sh1, (Sh_K1[MyStep])? HIGH:LOW); // записываем конечное значение
}
// *******************************************************************
void dimmer2 (void)      // ШИМ 2 канала  (рабочие дни)
{
byte Start_D;            // стартовое значение ШИМ канала
byte Stop_D;             // конечное значение ШИМ канала
int Sleep_D;           // задержка
if (DimT2[MyStep] != 0)  // если нужно плавно включить/выключить ШИМ канал
  {
  Start_D = (Sh_K2[MyStep_old]) ? 255:0; // вычисляем стартовое значение ШИМ канала (предыдущее состояние)
  Stop_D = (Sh_K2[MyStep]) ? 255:0;      // вычисляем конечное значение ШИМ канала (расписание)
  Sleep_D = DimT2[MyStep] * 3.9216;      // вычисляем задержку в мс. 3.9216 = 1000/255
  //--------------------------------------------------------------------
  SerialKanal(2, Start_D, Stop_D, Sleep_D); // включить для отладки
  //--------------------------------------------------------------------
  if (Start_D != Stop_D)                 // если изменилось
    {
    if (Start_D < Stop_D)
      {
      for (i=Start_D; i<Stop_D; i++)     // увеличиваем яркость
          {
          analogWrite(Sh2, i);
          delay (Sleep_D);
          }
      }
    else
      {
      for (i=Start_D; i>Stop_D; i--)     // уменьшаем яркость
          {
          analogWrite(Sh2, i);
          delay (Sleep_D);
          }
      }
    }
  }
digitalWrite(Sh2, (Sh_K2[MyStep])? HIGH:LOW); // записываем конечное значение
}
// *******************************************************************
void dimmer1_V (void)      // ШИМ 1 канала (выходные дни)
{
byte Start_D;              // стартовое значение ШИМ канала
byte Stop_D;               // конечное значение ШИМ канала
int Sleep_D;             // задержка
if (DimT1_V[MyStep] != 0)  // если нужно плавно включить/выключить ШИМ канал
  {
  Start_D = (Sh_K1_V[MyStep_old]) ? 255:0; // вычисляем стартовое значение ШИМ канала (предыдущее состояние)
  Stop_D = (Sh_K1_V[MyStep]) ? 255:0;      // вычисляем конечное значение ШИМ канала (расписание)
  Sleep_D = DimT1_V[MyStep] * 3.9216;      // вычисляем задержку в мс. 3.9216 = 1000/255
  //--------------------------------------------------------------------
  SerialKanal(1, Start_D, Stop_D, Sleep_D); // включить для отладки
  //--------------------------------------------------------------------
  if (Start_D != Stop_D)                   // если изменилось
    {
    if (Start_D < Stop_D)
      {
      for (i=Start_D; i<Stop_D; i++)       // увеличиваем яркость
          {
          analogWrite(Sh1, i);
          delay (Sleep_D);
          }
      }
    else
      {
      for (i=Start_D; i>Stop_D; i--)       // уменьшаем яркость
          {
          analogWrite(Sh1, i);
          delay (Sleep_D);
          }
      }
    }
  }
digitalWrite(Sh1, (Sh_K1_V[MyStep])? HIGH:LOW); // записываем конечное значение
}
// *******************************************************************
void dimmer2_V (void)      // ШИМ 2 канала  (выходные дни)
{
byte Start_D;              // стартовое значение ШИМ канала
byte Stop_D;               // конечное значение ШИМ канала
int Sleep_D;             // задержка
if (DimT2_V[MyStep] != 0)  // если нужно плавно включить/выключить ШИМ канал
  {
  Start_D = (Sh_K2_V[MyStep_old]) ? 255:0; // вычисляем стартовое значение ШИМ канала (предыдущее состояние)
  Stop_D = (Sh_K2_V[MyStep]) ? 255:0;      // вычисляем конечное значение ШИМ канала (расписание)
  Sleep_D = DimT2_V[MyStep] * 3.9216;      // вычисляем задержку в мс. 3.9216 = 1000/255
  //--------------------------------------------------------------------
  SerialKanal(2, Start_D, Stop_D, Sleep_D); // включить для отладки
  //--------------------------------------------------------------------
  if (Start_D != Stop_D)                   // если изменилось
    {
    if (Start_D < Stop_D)
      {
      for (i=Start_D; i<Stop_D; i++)       // увеличиваем яркость
          {
          analogWrite(Sh2, i);
          delay (Sleep_D);
          }
      }
    else
      {
      for (i=Start_D; i>Stop_D; i--)       // уменьшаем яркость
          {
          analogWrite(Sh2, i);
          delay (Sleep_D);
          }
      }
    }
  }
digitalWrite(Sh2, (Sh_K2_V[MyStep])? HIGH:LOW); // записываем конечное значение
}
 
// *******************************************************************
// Подпрограммы для DS3231
// *******************************************************************
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
// ---------------------------
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}
// ---------------------------
void setDateDs3231(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS3231_I2C_ADDRESS);
   Wire.write(0);
   Wire.write(decToBcd(second));    
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));     
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}
// ---------------------------
void getDateDs3231(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
 
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
 
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
 
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f); 
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}
// ---------------------------
 
// *******************************************************************
// Тестовая функция вывода времени в консоль
// *******************************************************************
void SerialTimeDate(void)
{
if (hour<10) Serial.print("0");
Serial.print(hour);
Serial.print(":");
if (minute<10) Serial.print("0");
Serial.print(minute);
Serial.print(":");
if (second<10) Serial.print("0");
Serial.print(second);
Serial.print(" ");
 
if (dayOfMonth<10) Serial.print("0");
Serial.print(dayOfMonth);
Serial.print(":");
if (month<10) Serial.print("0");
Serial.print(month);
Serial.print(":20");
Serial.print(year);
Serial.print(" DayW=");
Serial.print(dayOfWeek);
 
Serial.print("  Step=");
Serial.print(MyStep);
Serial.print(" SH1=");
Serial.print((Sh_K1[MyStep])? "HIGH ":"LOW ");
Serial.print(" SH2=");
Serial.print((Sh_K2[MyStep])? "HIGH ":"LOW ");
Serial.print(" Relay=");
Serial.print((Sh_R1[MyStep])? "HIGH ":"LOW ");
 
Serial.print("\n");
}
// ---------------------------
void SerialKanal(byte kan, byte s_t, byte s_p, int s_l)
{
SerialTimeDate();
if (kan <= 2)
  {
  Serial.print("Dimmer SH");
  Serial.print(kan);
  Serial.print(" Start=");
  Serial.print(s_t);
  Serial.print("  Stop=");
  Serial.print(s_p);
  Serial.print("  Sleep=");
  Serial.print(s_l);
  Serial.print("\n");
  }
}
// ---------------------------
 
Sasha80
Offline
Зарегистрирован: 18.01.2016

Извините за корявую вставку кода. Потом только на кнопочку внимание обратил!