Nouvelles:

Bienvenue au Forum de discussion Électro-Bidouilleur! Inscrivez-vous pour participer aux discussions!: 
https://forum.bidouilleur.ca/index.php?action=signup Les demandes d'inscription sont révisées quotidiennement.

Menu principal

PWM sur Arduino et fréquences

Démarré par diltech, Septembre 24, 2018, 05:33:13 PM

« précédent - suivant »

diltech

Bonjour,
Je travaille depuis plusieurs mois sur un régulateur pour une station de soudage. Il en existe un dégat sur Internet. Je ne comprend pas pourquoi certain fonctionne très bien avec mon alimentation à  découpage et la régulation est impécable et d'autre, dès je veux alimenter, mon PSU se reset constamment et il n'est pas possible de le faire fonctionner. J'utilise la version 24Volt 65W pour le fer. Certains codes font chauffer beaucoup trop mon IRL44N que j'utilise comme MOSFET, le code que j'utilise fait à  peine le mettre tiède avec un excellent rendement.

J'ai déjà  mon plan après avoir choisir le code qui fonctionne pour moi mais j'aimerais simplement comprendre ce qui se passe. Le montage matériel est identique ou très similaire à  la base. J'ai lu beaucoup mais c'est en anglais et j'en perds des bouts sur le fonctionnement du PWM du ATMEGA 328P.

Merci de vos lumière.

Curiosus

#1
Bonjour diltech,

Je pense que tu parles des IRLZ44N, si ça chauffe c'est ton voltage de gâte qui n'est pas bon.

La tension sur la gâte doit être proportionnel en fonction de ce que tu tires en courant.

Quand au PWM tu peux très bien le géré avec un NE555

As tu un schéma ?

A+


diltech

Bonjour,

Oui effectivement, il me manque un Z c'est bien le IRLZ44N. Voici le schéma de mon montage qui fonctionne très bien. J'attends ma commande de plaquette pour l'assemblage. J'ai utilisé un code qui possède des librairie pour le PWM. C'est la librairie Timer1 et le contrôle est fait avec le PID. Je sais que pour moi c'est plus simple car je ne suis pas très ferré en code C++.
Pour ma part, j'ai eu des problème de chauffe mais avec un code que j'ai trouvé, c'est résolu. Je voulais juste savoir pourquoi mon PSU débarque selon tel ou tel fréquence du PWM.

Voici le code que j'utilise, j'ai simplement réduit le PWM max à  900 au lieu de 1023 et le PSU ne ferme plus.


#include <Wire.h>
#include "LiquidCrystal.h"
#include "TimerOne.h"
#include "Button.h"
#include "PID_v1.h"
#include "PID_AutoTune_v0.h"
#include "EEPROMex.h"
#include <avr/wdt.h>

#define OFF 0
#define ON 1

// PIN DEFINITIONS
#define HEATER 9
#define TEMP_PIN 21
#define POT 20
#define REED 18

#define Button1 8
#define Button2 7
#define Button3 4
#define Button4 19
#define Buzzer 13
//LCD
#define LCD_LED 10
#define LCD_RS 17
#define LCD_EN 16
#define LCD_D4 15
#define LCD_D5 14
#define LCD_D6 12
#define LCD_D7 11
//LED
const int LED_R = 6;
const int LED_G = 5;
const int LED_B = 3;
int flash_on = 0;
int flash_off = 0;

//SETTINGS
char ver[] = "0.8";
int boot_screen = 1;
#define TEMP_WO_IRON 749 // readTemp(); returns about 749 when I disconnect the iron
#define LCD_INTERVAL 200 // Time im ms between LCD updates
#define PTC_INTERVAL 100 // Time im ms between average analog readings
#define FLASH_ON 600 // Time im ms for RGB to stay on when flashing, keep it multiple of LCD_INTERVAL
#define FLASH_OFF 400 // Time im ms for RGB to stay off when flashing, keep it multiple of LCD_INTERVAL
#define RGB_EFECT_MIN 60 // degrees below temperature to start the RGB effect with blue color
#define RGB_EFECT_MAX 30 // degrees above temperature to finish the RGB effect with red color
#define BAR_STEP 4 // graph will move every 4ËšC
#define AUTO_SLEEP_TIME 30000 // Auto sleep time
#define AUTO_OFF_TIME 300000// Auto OFF time if iron is in sleep mode
#define SAFETY_OFF_TIME 5000 // Auto OFF time if temp exceeds max+30
#define BUZ_DUR 40 //buzzer sound duration

// Temperature control definitions
#define MIN_TEMP 200 // Minimum setpoint temperature, sleep temp = min - 50
#define MAX_TEMP 500 // Maximum setpoint temperature, turn off temp = max + 30
#define PWM_MAX 900 // PWM limit, max 1023

// Y = a*X + b, where Y is the temperature and X is the analog value read from the sensor.
#define EQUATION_A 0.70
#define EQUATION_B -170

// PID VALUES
#define KP_VAL 20.00
#define KI_VAL 3.50
#define KD_VAL 25.00

// PID Autotune Variables
//Setup a High Temp for Autotune e.g. 250ËšC
//Preheat the Iron at a lower temp like 200ËšC and start autotune with a preheated iron.
//Don't use a cold iron because it gives momentarely false readings at low temperatures
//and the Autotune algorithm won't calculate correct P,I,D parameters.
#define AUTOTUNE_SETPOINT 250 // Temperature around PID autotune will tune
#define AUTOTUNE_START_VALUE (PWM_MAX/2) // Do not change
#define AUTOTUNE_STEP_VALUE AUTOTUNE_START_VALUE // Do not change
#define AUTOTUNE_NOISEBAND 3
#define AUTOTUNE_LOOKBACK 10

int bright = 0; //brightness of LCD (1..10)
int temp_5 = OFF; //multiples of 5
int autoTurnOFF = OFF; //
uint8_t showAnalog = ON; //show analog values in PID values view

// Global variables
uint32_t last_lcd_update = 0;
uint32_t last_ptc_update = 0;
uint8_t heater_mode = OFF;
uint8_t sleeping = OFF;
uint8_t ironLifted = OFF;
uint32_t base_time = 0;
uint32_t sleeping_time = 0;
uint32_t overshoot_time = 0;
uint8_t showPID = OFF;
uint8_t clearEEPROM = OFF;

// PID Variables
double temperature;
double setpoint = 0.0;
double duty;
double kp;
double ki;
double kd;
uint16_t autotune_address;
uint16_t kp_address;
uint16_t ki_address;
uint16_t kd_address;
uint16_t bright_address;
uint16_t temp_5_address;
uint16_t autoTurnOFF_address;

PID heaterPid(&temperature, &duty, &setpoint, 2, 5, 1, DIRECT);
PID_ATune aTune(&temperature, &duty);
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
Button heatButton = Button(Button1, LOW); // start/stop heating, start autotune
Button increaseBrightButton = Button(Button2, LOW); // change lcd brightness
Button temp_5_Button = Button(Button3, LOW); // enable or disable showing temp as multiple of 5
Button pidButton = Button(Button4, LOW); //show PID constants, save EEPROM on exit, reset EEPROM

void setup() {

// Autotune
uint8_t autotune = OFF;
uint8_t autotune_pid = 0;

// Enable Watchdog Timer, 1 second
wdt_enable(WDTO_1S);

// Define the EEPROM address for Kp, Ki and Kd
autotune_address = EEPROM.getAddress(sizeof(uint8_t));
kp_address = EEPROM.getAddress(sizeof(double));
ki_address = EEPROM.getAddress(sizeof(double));
kd_address = EEPROM.getAddress(sizeof(double));
bright_address = EEPROM.getAddress(sizeof(int));
temp_5_address = EEPROM.getAddress(sizeof(int));
autoTurnOFF_address = EEPROM.getAddress(sizeof(int));

// Set up pins
pinMode(LCD_LED, OUTPUT);
pinMode(HEATER, OUTPUT);
pinMode(LED_R, OUTPUT);
pinMode(LED_G, OUTPUT);
pinMode(LED_B, OUTPUT);
pinMode(Buzzer, OUTPUT);
pinMode(Button1, INPUT_PULLUP);
pinMode(Button2, INPUT_PULLUP);
pinMode(Button3, INPUT_PULLUP);
pinMode(Button4, INPUT_PULLUP);
pinMode(REED, INPUT_PULLUP);

// Set up Heater PWM
Timer1.pwm(HEATER, 0, 20);

// Set up PID
heaterPid.SetOutputLimits(0, PWM_MAX);
heaterPid.SetSampleTime(50); // Update PID every 50ms
heaterPid.SetMode(AUTOMATIC);

// Set up LCD
setBrightness(bright);
lcd.begin(16, 2);
charSetup();

//Check if reset EEPROM button is pressed at startup
if (digitalRead(Button4) == 0) {
clearEEPROM = ON;
}
// Check if PID autotune button is pressed at startup
else if (digitalRead(Button1) == 0) {
autotune = ON;
}
//Reset EEPROM
if (clearEEPROM){
setBrightness(10);
lcd.clear();
lcd.print(" EFFACER EEPROM ? ");
lcd.setCursor(0, 1);
lcd.print("   [OUI] [NON]   ");
while (clearEEPROM){
if (digitalRead(Button2) == 0){
EEPROM.writeByte(autotune_address, 0);
EEPROM.writeDouble(kp_address, 0);
EEPROM.writeDouble(ki_address, 0);
EEPROM.writeDouble(kd_address, 0);
EEPROM.writeInt(bright_address, 0);
EEPROM.writeInt(temp_5_address, 0);
EEPROM.writeInt(autoTurnOFF_address, 0);
lcd.clear();
lcd.print("EEPROM VIDE");
lcd.setCursor(0, 1);
lcd.print(" 3 POUR SORTIR ");
for (int i = 0; i < 2; i++){
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
delay(BUZ_DUR*15);
}
}
else if (digitalRead(Button3) == 0){
clearEEPROM = OFF;
}
wdt_reset();
}

}
// Start PID autotune
else if (autotune){
setBrightness(10);
lcd.clear();
lcd.print("Calibrer le PID?");
lcd.setCursor(0, 1);
lcd.print("Oui: 2 || NON: 3");
while (autotune){
if (digitalRead(Button2) == 0){
// Configure PID autotune
setpoint = AUTOTUNE_SETPOINT;
duty = AUTOTUNE_START_VALUE;
aTune.SetNoiseBand(AUTOTUNE_NOISEBAND);
aTune.SetOutputStep(AUTOTUNE_STEP_VALUE);
aTune.SetLookbackSec(AUTOTUNE_LOOKBACK);
aTune.SetControlType(1);

// Print some autotune info
lcd.clear();
lcd.print("Calibration sur:");
lcd.setCursor(0, 1);
lcd.print((uint16_t)setpoint);
lcd.write(byte(9));
lcd.print("C");

// Heat to the setpoint, temperature will rise above it
Timer1.setPwmDuty(HEATER, duty);
while(readTemp() < setpoint) {
// Reset the watchdog timer to prevent rebooting
wdt_reset();
}

// Wait for temperature to drop to setpoint
Timer1.setPwmDuty(HEATER, 0);
while(readTemp() > setpoint) {
// Reset the watchdog timer to prevent rebooting
wdt_reset();
}

// Start the autotune
while(autotune) {
// Get the current temperature
temperature = readTemp();

// Check if the autotune is finished
if(aTune.Runtime() != 0) {
autotune = OFF;
}
else {
Timer1.setPwmDuty(HEATER, duty);
}

// If finished, set up the PID and EEPROM values
if(!autotune) {

// Turn off the heater
Timer1.setPwmDuty(HEATER, 0);

// Get the values from autotune
kp = aTune.GetKp();
ki = aTune.GetKi();
kd = aTune.GetKd();

// Write them to the EEPROM
EEPROM.writeDouble(kp_address, kp);
EEPROM.writeDouble(ki_address, ki);
EEPROM.writeDouble(kd_address, kd);
EEPROM.writeByte(autotune_address, 1);

// Reset the setpoint
setpoint = 0.0;
}
wdt_reset();
}
for (int i = 0; i < 5; i++){
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
delay(BUZ_DUR);
}
}
else if (digitalRead(Button3) == 0){
autotune = OFF;
}
wdt_reset();
}
}

bright = EEPROM.readInt(bright_address);
setBrightness(bright);

if(boot_screen){
if (digitalRead(REED)){
lcd.clear();
lcd.print("Station Soudage");
lcd.setCursor(0, 1);
lcd.print("HAKKO 907   ");
lcd.print(ver);

}
}
while (boot_screen){
if (!digitalRead(REED)){
boot_screen = 0;
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
     digitalWrite(Buzzer, HIGH);
     delay(BUZ_DUR);
     digitalWrite(Buzzer, HIGH);
     delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}
wdt_reset();
}

temp_5 =  EEPROM.readInt(temp_5_address);
autoTurnOFF = EEPROM.readInt(autoTurnOFF_address);

// Get the PID constant values from EEPROM if autotune was run
autotune_pid = EEPROM.readByte(autotune_address);
if(autotune_pid == 1) {
kp = EEPROM.readDouble(kp_address);
ki = EEPROM.readDouble(ki_address);
kd = EEPROM.readDouble(kd_address);
}
else{
kp = KP_VAL;
ki = KI_VAL;
kd = KD_VAL;
}

heaterPid.SetTunings(kp,ki,kd);

lcd.clear();
}

void loop() {
uint32_t current_time = millis(); // Get the current time

wdt_reset();
checkButton();

// Automatic turn-off
if(heater_mode) {
//if left on base and lifted at least once
if(!(digitalRead(REED)) && (ironLifted)){
if (autoTurnOFF) {
if (sleeping){
if ((millis() - sleeping_time) >= AUTO_OFF_TIME){
heater_mode = OFF;
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}
}
else if ((millis() - base_time) >= AUTO_SLEEP_TIME) {
sleeping = ON;
setpoint = MIN_TEMP - 50;
sleeping_time = millis();
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}
}
}
//lifted from base or hasn't lifted at least once
else{
if (sleeping){
sleeping = OFF;
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}
else if (digitalRead(REED)) ironLifted = ON;
base_time = millis();
setpoint = readPot();
}
}
else setpoint = readPot();

// Read Analog data for PTC
if(current_time - last_ptc_update > PTC_INTERVAL) {
temperature = readTemp();
if(heater_mode){
if (temperature > MAX_TEMP + 30){
if (millis() - overshoot_time >= SAFETY_OFF_TIME){
heater_mode = OFF;
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}
}
else overshoot_time = millis();
lightRGB(setpoint, temperature);
}
last_ptc_update = current_time;
}

heaterPid.Compute(); // Calculate PID value
// Adjust PWM Duty based on the PID
if(heater_mode) {
Timer1.setPwmDuty(HEATER, duty);
} else {
Timer1.setPwmDuty(HEATER, 0);
}

//Check if it's time to update the LCD
if(current_time - last_lcd_update > LCD_INTERVAL) {
lcd.setCursor(0, 0);
if((temperature > TEMP_WO_IRON-5) && (temperature < TEMP_WO_IRON+5)){
heater_mode = OFF;
lcd.print("     S.V.P.     ");
lcd.setCursor(0, 1);
lcd.print("Brancher le fer ");
if (flash_on < FLASH_ON/LCD_INTERVAL){ // stay on for FLASH_ON ms
setColor(255, 0, 0);  // red
flash_on++;
flash_off = 0;
}
else{
if(flash_off < FLASH_OFF/LCD_INTERVAL){ // stay off for FLASH_OFF ms
setColor(0, 0, 0);
flash_off++;
}
else flash_on = 0;
}
}
else{
if (!showPID) {
//1st Row
lcd.write(byte(0));
lcd.print(' ');
if (temp_5){
if (temperature < 98) lcd.print(' ');
if (int(temperature) % 5 < 3){
lcd.print(int(temperature / 5) * 5);
}
else{
lcd.print(int(temperature / 5 + 1) * 5);
}
}
else{
if (temperature < 100) lcd.print(' ');
lcd.print(temperature, 0);
}
lcd.write(byte(9));
lcd.print("C ");
printGraph(setpoint, temperature);
//2nd Row
lcd.setCursor(0, 1);
if (!digitalRead(REED)) lcd.print(char(219));
else lcd.print(" ");
lcd.print(" ");
lcd.print(setpoint, 0);
lcd.write(byte(9));
lcd.print("C ");

//print duty
int power;
if (heater_mode) power = map(duty, 0, PWM_MAX, 0, PWM_MAX/1023*100);
else power = 0;
if (power < 10) lcd.print("  ");
else if (power < 100) lcd.print(" ");
lcd.print(power);
lcd.print("% ");

if (heater_mode){
if (sleeping) lcd.print("_zZ");
else{
lcd.print(" ");
//lcd.write(byte(1));
lcd.print("ON");
}
}
else{
lcd.print("OFF");
}
}
else displayPid();
if (!heater_mode) setColor(255, 255, 255);  // white
}
last_lcd_update = current_time;
}
}

// Read Iron temperature
uint16_t readTemp() {
uint16_t temp = 0;
// Discard first reading
analogRead(TEMP_PIN);
// Read temperature eight times
for (int i = 0; i < 8; i++){
temp += analogRead(TEMP_PIN);
}
temp = (temp >> 3);
temp = (EQUATION_A*temp) + EQUATION_B;
return temp;
}

uint16_t readPot() {
uint16_t pot = 0;

// Discard first reading
analogRead(POT);
// Read the potentiometer four times
pot += analogRead(POT);
pot += analogRead(POT);
pot += analogRead(POT);
pot += analogRead(POT);

// Map the value read to the temperature range
pot = map(pot, 0, 4092, MIN_TEMP, MAX_TEMP);

if (pot % 5 < 3) return pot / 5 * 5;
else return (pot / 5 + 1) * 5;
}

// Check if heater start button was pressed
void checkButton() {
heatButton.listen();
increaseBrightButton.listen();
temp_5_Button.listen();
pidButton.listen();

//Button1
if(heatButton.onPress()) {
if (showPID) autoTurnOFF = !autoTurnOFF;
else{
if (heater_mode){
heater_mode = OFF;
}
else{
ironLifted = OFF;
overshoot_time = millis();
heater_mode = ON;
}
}
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}

//Button2
if (increaseBrightButton.onPress()){
if (++bright > 10) bright = 1;
setBrightness(bright);
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}

//Button3
if (temp_5_Button.onPress()){
  digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}

//Button4
if (pidButton.onPress()){
if (!showPID){
showPID = ON;
}
else{
showPID = OFF;
EEPROM.writeInt(bright_address, bright);
EEPROM.writeInt(temp_5_address, temp_5);
EEPROM.writeInt(autoTurnOFF_address, autoTurnOFF);
}
digitalWrite(Buzzer, HIGH);
delay(BUZ_DUR);
digitalWrite(Buzzer, LOW);
}
}

// Display PID Constants
void displayPid() {
lcd.clear();
lcd.print("P:");
lcd.print(kp, 2);
lcd.print(" I:");
lcd.print(ki, 2);
if(temp_5) lcd.print(" 5");
else lcd.print(" 1");
lcd.setCursor(0, 1);
lcd.print("D:");
lcd.print(kd, 2);

lcd.print(" slp");
if (autoTurnOFF) lcd.print("Y");
else lcd.print("N");

lcd.print(" ");

if (showAnalog){
uint16_t temp_analog = 0;
for (int i=0; i<5; i++){
temp_analog += analogRead(TEMP_PIN);
}
lcd.print(temp_analog/5);
}
else lcd.print("    ");
}

void setBrightness(int light){
light = map(light, 0, 10, 245, 10);
analogWrite(LCD_LED, light);
}

void setColor(int red, int green, int blue){
analogWrite(LED_R, 255-red);
analogWrite(LED_G, 255-green);
analogWrite(LED_B, 255-blue); 
}

void lightRGB(double setpoint, double termperature){
double diff = setpoint - temperature;
if (diff > RGB_EFECT_MIN) diff = RGB_EFECT_MIN;
else if (diff < -RGB_EFECT_MAX) diff = -RGB_EFECT_MAX;
if (diff < 0){
diff = map(diff, -RGB_EFECT_MAX, 0, 255, 0);
setColor(diff, 255-diff, 0);
}
else{
diff = map(diff, 0, RGB_EFECT_MIN, 0, 255);
setColor(0, 255-diff, diff);
}
}

void printGraph(double setpoint, double termperature){

double diff = temperature - setpoint;
int boxes;
if (diff > BAR_STEP*7) boxes = 7;
else if (diff < -BAR_STEP*7) boxes = -7;
else boxes = diff / BAR_STEP;
int blanks = -abs(boxes)/2+3.5;

//if temp = setpoint
if (boxes == 0){
for (int i = 0; i < 3; i++){
lcd.write(byte(2));
}
lcd.write(byte(3));
lcd.write(byte(4));
for (int i = 0; i < 3; i++){
lcd.write(byte(2));
}
}

//if temp < setpoint
else if (boxes < 0) {
//print blanks
for (int i = 0; i < blanks; i++){
lcd.write(byte(2));
}
//print first box
if (boxes %2 == 0) lcd.write(byte(3));
else lcd.write(byte(5));
//print full box/es
for (int i=0; i < 3-blanks; i++){
lcd.write(byte(7));
}
//print 4 blanks
for (int i=0; i < 4; i++){
lcd.write(byte(2));
}
}

//if temp > setpoint
else{
//print 4 blanks
for (int i = 0; i < 4; i++){
lcd.write(byte(2));
}
//print full box/es
for (int i=0; i < 3-blanks; i++){
lcd.write(byte(7));
}
//print last box
if (boxes %2 == 0) lcd.write(byte(4));
else lcd.write(byte(6));
//print blanks
for (int i = 0; i < blanks; i++){
lcd.write(byte(2));
}
}
}

/*
|    2    |    3    |    4    |    5    |    6   |    7    |
|  ## ##  |  ## ##  |  ## ##  |  ## ##  |  ## ##  |  ## ##  |
|         |         |         |         |         |         |
|         |         |         |     ##  |  ##     |  ## ##  |
|         |     ##  |  ##     |  ## ##  |  ## ##  |  ## ##  |
|         |     ##  |  ##     |  ## ##  |  ## ##  |  ## ##  |
|         |         |         |     ##  |  ##     |  ## ##  |
|         |         |         |         |         |         |
|  ## ##  |  ## ##  |  ## ##  |  ## ##  |  ## ##  |  ## ##  |
*/
void charSetup() { 
byte therm[8] = {0b10010,0b11010,0b10010,0b11010,0b10010,0b11110,0b11110,0b11110};
byte on[8] = {0b00100,0b00100,0b10101,0b10001,0b10001,0b10001,0b01110,0b00000};
  byte degree[8] = {
    B00010,
    B00101,
    B00010,
    B00000,
    B00000,
    B00000,
    B00000,
  };
byte bar[7][8] = {
{0b11011,  0b00000,  0b00000,  0b00000,  0b00000,  0b00000,  0b00000,  0b11011 },
{0b11011,  0b00000,  0b00000,  0b00011,  0b00011,  0b00000,  0b00000,  0b11011 },
{0b11011,  0b00000,  0b00000,  0b11000,  0b11000,  0b00000,  0b00000,  0b11011 },
{0b11011,  0b00000,  0b00011,  0b11011,  0b11011,  0b00011,  0b00000,  0b11011 },
{0b11011,  0b00000,  0b11000,  0b11011,  0b11011,  0b11000,  0b00000,  0b11011 },
{0b11011,  0b00000,  0b11011,  0b11011,  0b11011,  0b11011,  0b00000,  0b11011 }
};
lcd.createChar(0, therm);
lcd.createChar(1, on);
  lcd.createChar(9, degree) ;
lcd.createChar(2, bar[0]);
lcd.createChar(3, bar[1]);
lcd.createChar(4, bar[2]);
lcd.createChar(5, bar[3]);
lcd.createChar(6, bar[4]);
lcd.createChar(7, bar[5]);
}



Je joint le code et les photos du proto par la même occasion.

Au plaisir.

Curiosus

#3
Bonjour diltech,

Personnellement je connais pas ATMEGA 328P, j'utilise pour ma part des microcontrôleurs PIC, le langage que je pratique est ASM, ce qui me permet de bien comprendre le fonctionnement du microcontrôleur

Sur les microcontrôleurs Pic existe aussi un timer1, je pense qu'un ATMEGA 328P fonctionne de la même manière.

Si ton PWM dépasse un seuil, deux choses risquent de se produire, soit plus rien, soit plantage.

Le Timer1 fonctionne sur le débordement d'un temps, avec des prédiviseurs qu'on peu activer, ou désactivé, ce qui permet
d'avoir une Fréquence du PWM réglable.

Le PWM dépend de la fréquence de ton quartz, ou de l'oscillateur interne de ton AMEGA 328P.

Pour une certaine Fréquence tu auras un PWM à  99%, et pour d'autre Fréquence tu ne pourras pas dépasser les 10%, 20%
, 30%, 40%, 50% ...etc...

Si cette fréquence est mal réglée pas rapport à  ce que tu lui demandes, il y  aura arrêt du PWM, de plus, si tu mets une valeur trop
grande, ton microcontrôleur va planter(comme Windows)

J'ai écrit un programme pour microcontrôleur PIC pour éviter ce genre de problème.

La solution à  ton problème, il faut changer la fréquence du PWM, je te parle de fréquence, pas de modulation.

A propos des IRLZ44N, éviter de commander la gâte en linéaire pour une régulation de forte intensité, de plus il faut une fréquence du PWM assez rapide, sinon il risque de chauffer.

Beau projet, j'espère bien le voir aboutir, merci de le partager.


   A+

diltech

Allo,

Alors j'ai trouvé ce que je cherchais, à  savoir le fonctionnement des différentes pins PWM sur l'atmega. Je savais qu'il ne fonctionnaient pas tous de la même façon selon la pin utilisée.

https://sites.google.com/site/qeewiki/books/avr-guide/pwm-on-the-atmega328

Maintenant je comprends un peu mieux la façon d'appliqué un diviseur et je vois que certain code utilise une librairie et d'autre mettre le même code dans une fonction.

Pour ma part, mon projet semble fonctionné et ma température reste assez stable. J'ai essayé de travaillé toute la semaine avec ma station et il me reste à  recevoir mes plaquettes pour effectué le montage finale. Je vais publié les étapes de la fabrication.

Merci encore. J'en ai encore beaucoup à  apprendre sur le sujet.

:D

Curiosus

#5
Bonsoir diltech,


Peux tu me dire ce que tu as utiliser comme capteur de température,  me mettre un lien dessus.

J'en recherche un pour un projet que j'ai commencé, mais je sais vraiment pas le quelle choisir, ma température
ne dépassera pas 250 degrés.

Pour le lien sur le PWM  que tu indiques, c'est super bien expliqué, on voie clairement les registres qu'il faut toucher, pour avoir
une fréquence différente du PWM, il explique même les registres qui s'occupe du prédiviseurs :)

   A+   

diltech

Salut,

Je ne suis pas sûr de bien comprendre ta question. Pour calibrer mon élément, je me suis servie de mon multimètre qui possède une sonde thermique par contact.
Ensuite, je calibre avec les valeurs haut et bas que la thermistor sur l'élément me donne, genre à  100C et à  400C. À partir d'un diviseur de tension, la résistance envoie une valeur analogique qui est amplifié par mon MCP601. Dans le code il y a une formule pour renseigner le PID en trouvant deux valeurs à  partir des températures et des valeurs analogique.
Par la suite, le programme se calibre automatiquement à  250C mais il faut faire un fine tuning manuels avec mon multimètre mais on est jamais loin des valeurs désirée. On ajuste une des deux valeurs par incrémentation de 0.5 et on trouve très vite notre cible.

En espérant avoir répondu correctement à  ta question.

Salutation,

Curiosus

#7
Bonjour,


Ce que je voulais savoir, c'est qu'est ce que tu utilises comme thermistor(thermistance).

Est t'elle intégrés dans le fer à  souder ?


Merci pour les renseignements

diltech

Bonjour,

Oui effectivement, la résistance thermique est intégré dans l'élément qui se retrouve facile sur EBAY.

https://www.ebay.ca/itm/50W-AC24V-Soldering-Heating-Element-Heater-For-Hakko-900M-900L-907-908-913-A1321/311224946415?hash=item487673ceef:g:OuYAAOSw2XFUlnXm

Moi j'utilise celui-ci qui est d'une très bonne qualité mais j'avais déjà  un fer 907.

Au plaisir.

Curiosus

#9
Bonjour,

Ok, merci pour tous c'est renseignements. :) 

Voici l'appareille que je me suis fait pour faire mes PCB : https://www.youtube.com/watch?v=ql8daDENUMk

Je suis entrains de le modifier, ce qui explique la curiosité sur la thermistance, mais au plus précis j'obtiens ceci

diltech

Allo,

C'est assez impressionnant de voir le résultat de ta technique pour faire les plaquettes. J'ai bien essayé de mon côté et j'ai la possibilité d'avoir des presses haute température au travail. J'ai utilisé l'endos (le backing) d'étiquette autocollante qui s'imprime très bien avec une imprimante laser. L'avantage, c'est qu'on n'a pas besoin de développé dans un liquide puisque la poudre n'adhère pas au papier anti-adhésif.

Par contre, je trouve les résultats un peu aléatoires pour les petites pistes et c'est quasi impossible de faire des vias. En ce qui me concerne, j'aime mieux me tourner pour une fabrication externe comme PCBWAY. Avec un court délai d'une douzaine de jours de livraison et aussi le fait que les coûts sont très peu élevé, je trouve meilleur compte.

Bravo très beau projet.


Au plaisir.