Version corrigée testée fontionnelle

This commit is contained in:
ddr
2026-07-01 22:43:25 +02:00
parent 18280e01ac
commit 5788f48001
37 changed files with 14353 additions and 4054 deletions
@@ -0,0 +1,5 @@
(kicad_symbol_lib
(version 20241209)
(generator "kicad_symbol_editor")
(generator_version "9.0")
)
@@ -0,0 +1,303 @@
(kicad_symbol_lib
(version 20241209)
(generator "kicad_symbol_editor")
(generator_version "9.0")
(symbol "IRLML0030TRPbF"
(pin_names
(hide yes)
)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(property "Reference" "Q3"
(at 6.35 1.2701 0)
(effects
(font
(size 1.27 1.27)
)
(justify left)
)
)
(property "Value" "TSM320N03CX RFG"
(at 6.35 -1.2699 0)
(effects
(font
(size 1.27 1.27)
)
(justify left)
)
)
(property "Footprint" "Package_TO_SOT_SMD:TSOT-23_HandSoldering"
(at 5.08 -1.905 0)
(effects
(font
(size 1.27 1.27)
(italic yes)
)
(justify left)
(hide yes)
)
)
(property "Datasheet" "https://services.taiwansemi.com/storage/resources/datasheet/TSM320N03CX_C1811.pdf"
(at 5.08 -3.81 0)
(effects
(font
(size 1.27 1.27)
)
(justify left)
(hide yes)
)
)
(property "Description" "MOSFET N-CHANNEL 30V 5.5A SOT23"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_keywords" "n channel fet"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_fp_filters" "SOT?223*"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(symbol "IRLML0030TRPbF_0_1"
(polyline
(pts
(xy 0.254 1.905) (xy 0.254 -1.905)
)
(stroke
(width 0.254)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 0.254 0) (xy -2.54 0)
)
(stroke
(width 0)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 0.762 2.286) (xy 0.762 1.27)
)
(stroke
(width 0.254)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 0.762 0.508) (xy 0.762 -0.508)
)
(stroke
(width 0.254)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 0.762 -1.27) (xy 0.762 -2.286)
)
(stroke
(width 0.254)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 0.762 -1.778) (xy 3.302 -1.778) (xy 3.302 1.778) (xy 0.762 1.778)
)
(stroke
(width 0)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 1.016 0) (xy 2.032 0.381) (xy 2.032 -0.381) (xy 1.016 0)
)
(stroke
(width 0)
(type default)
)
(fill
(type outline)
)
)
(circle
(center 1.651 0)
(radius 2.794)
(stroke
(width 0.254)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 2.54 2.54) (xy 2.54 1.778)
)
(stroke
(width 0)
(type default)
)
(fill
(type none)
)
)
(circle
(center 2.54 1.778)
(radius 0.254)
(stroke
(width 0)
(type default)
)
(fill
(type outline)
)
)
(circle
(center 2.54 -1.778)
(radius 0.254)
(stroke
(width 0)
(type default)
)
(fill
(type outline)
)
)
(polyline
(pts
(xy 2.54 -2.54) (xy 2.54 0) (xy 0.762 0)
)
(stroke
(width 0)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 2.794 0.508) (xy 2.921 0.381) (xy 3.683 0.381) (xy 3.81 0.254)
)
(stroke
(width 0)
(type default)
)
(fill
(type none)
)
)
(polyline
(pts
(xy 3.302 0.381) (xy 2.921 -0.254) (xy 3.683 -0.254) (xy 3.302 0.381)
)
(stroke
(width 0)
(type default)
)
(fill
(type none)
)
)
)
(symbol "IRLML0030TRPbF_1_1"
(pin input line
(at -5.08 0 0)
(length 2.54)
(name "G"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "1"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin passive line
(at 2.54 5.08 270)
(length 2.54)
(name "D"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "3"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin passive line
(at 2.54 -5.08 90)
(length 2.54)
(name "S"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "2"
(effects
(font
(size 1.27 1.27)
)
)
)
)
)
(embedded_fonts no)
)
)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,4 @@
(sym_lib_table
(version 7)
(lib (name "Project_Library")(type "KiCad")(uri "${KIPRJMOD}/Project_Library.kicad_sym")(options "")(descr ""))
)
Binary file not shown.
+42 -12
View File
@@ -39,37 +39,38 @@ Pour créer un PWM le code Arduino suivant va s'occuper de :
- Générer un PWM de sortie
```
// High-frequency PWM using Timer2 on pins 3 & 11 (31 kHz)
const int pwmPin1 = 11;     // OC2B
const int pwmPin2 = 3;    // OC2A
const int analogPin1 = A0;
const int analogPin2 = A1;
// High-frequency PWM using Timer2 on digital outputs D3 & D11 (31 kHz)
const int pwmPin1 = 11;     // OC2B, Pin 15 sur le 328P, pilote Q1
const int pwmPin2 = 3;    // OC2A, Pin 1 sur le 328P, pilote Q2
const int analogPin1 = A0; //J2 Manette Gauche, Pin 23 sur le 328P
const int analogPin2 = A1; //J4 Manette Millieu, Pin 24 sur le 328P
void setup() {
  pinMode(pwmPin1, OUTPUT);
  pinMode(pwmPin2, OUTPUT);
 
  pinMode(analogPin1, INPUT);
  pinMode(analogPin2, INPUT);
  // ----- Timer2 Fast PWM (8-bit), no prescaler -----
  TCCR2A = _BV(WGM20) | _BV(WGM21) | _BV(COM2A1) | _BV(COM2B1);
  TCCR2B = _BV(CS20);  // No prescaler → 31.37 kHz
 
  Serial.begin(9600);
}
void loop() {
  int adc1 = analogRead(analogPin1);
  int adc2 = analogRead(analogPin2);
  if (adc1 <= 100){ // pour éteindre lorsque la télécomande est relachée
  if (adc1 <= 100){
    adc1 = 0;}
  if (adc2 <= 100){ // pour éteindre lorsque la télécomande est relachée
  if (adc2 <= 100){
    adc2 = 0;}
  uint8_t pwm1 = map(adc1, 0, 1023, 0, 255);
  uint8_t pwm2 = map(adc2, 0, 1023, 0, 255);
  OCR2B = pwm2;   // Pin 3
  OCR2A = pwm2;   // Pin 11
  OCR2B = pwm1;   // D3, J2 Manette Gauche, Pin 1 sur le 328P, pilote Q3
  OCR2A = pwm2;   // D11, J4 Manette Millieu Pin 15 sur le 328P, pilote Q1
}
```
@@ -86,7 +87,9 @@ Pour miniaturiser le concept va retenir :
- Un port JTAG pour reprogrammer au besoin le processeur.
![](_docAssets/SchemaCircuitCarerra.jpg)
Pour valider que le Mosfet N-channel puisse bien être piloté, une simulation du circuit à été faite dans LTSpice:
![](_docAssets/SimulationLTSpice.jpg)
Le PCB sur lequel seront soudés les composants et qui reprends les pistes pour les télécommandes et le raccordement de puissance d'origine.
@@ -98,6 +101,33 @@ Et la commande qui arrivera bientôt :
![](_docAssets/PCBOrder.jpg)
La soudure à été réalisée avec de la pâte a souder, d'abord on met des gouttes sur toutes les pastilles, on y colle les composants et on fait fondre. Le circuit est fonctionnel, mais j'ai fait une erreur de positionnement qui va me déranger pour mettre le circuit en place : La diode D5 est à un endroit qui m'oblige à retirer un peu de plastique.
On voit aussi C1 qui est remplacé par un électrolytique car je n'ai pas commandé la bonne référence.
![](_docAssets/CircuitTerminé.jpg)
Pour programmer la carte ci-dessus j'utilise la méthode : Méthode #4 : programmation d’un ATmega328P en ISP, avec un Arduino Uno transformé en programmateur décrite sur le site [https://passionelectronique.fr/programmer-atmega328p/#methode-4-programmation-dun-atmega328p-en-isp-avec-un-arduino-uno-transforme-en-programmateur]()
![](_docAssets/ArduinoAsISP.png)
Le montage réalisé avec à gauche le programmateur, et a droite le contrôleur à programmer.
![](_docAssets/Pasted%20image%2020260607220442.png)
Ensuite dans ArduinoIDE
Bon cette première version du contrôleur de circuit fonctionne mais n'est pas fiable...
Après quelques minutes de jeu sur le circuit je casse Q1 ou Q2. J’imagine que le problème viens de petit courts-circuits sur la piste lorsque les balais de la voiture viennent à toucher les deux rails. D'une part Q1 et Q2 sont limites pour ce moteur, d'autre part il n'y a aucune protection contre les sur-intensités sur ce circuit.
Dans la deuxième version, j'ai laissé passer une erreur dans la conception du PCB qui s'est retrouvée sur le circuit fabriqué...
![](_docAssets/Pasted%20image%2020260607234007.png)
Il a fallu gratter la piste pour rattraper le faux contact entre ADC3 et la piste U1-PD3. J'ai pu aussi trouver deux autres problèmes de design. Tout d'abord une piste bien trop petite :
![](_docAssets/Pasted%20image%2020260701220914.png)
Un condensateur permettant de réduire le bruit de mesure à ajouter :
![](_docAssets/Pasted%20image%2020260701220941.png)
Tout celà à été corrige dans le fichier KiCad mais non mis en production. Je garde le circuit "bricolé" à la main avec les erreurs corrigées en grattant dans le jouet actuel car cela fonctionne.
Binary file not shown.

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@@ -1,106 +1,70 @@
// High-frequency PWM using Timer2 on pins 3 & 11
const int pwmPin1 = 11; // OC2B
const int pwmPin2 = 3; // OC2A
bool readADC2 = true;
// PWM using Timer2 on digital outputs D3 & D11
const int pwmPin1 = 11; // OC2B, D11 = Pin 15 sur le 328P, pilote Q1
const int pwmPin2 = 3; // OC2A, D3 = Pin 1 sur le 328P, pilote Q3
const int led3 = 1; // D1 aussi utilisée par le port série
const int led4 = 0; // D0 aussi utilisée par le port série
void setup() {
pinMode(pwmPin1, OUTPUT);
pinMode(pwmPin2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(A0, INPUT); //J2 Manette Gauche, Pin 23 sur le 328P
pinMode(A1, INPUT); //J4 Manette Millieu, Pin 24 sur le 328P
pinMode(A2, INPUT); //Courant Q3, Pin 25 sur le 328P
pinMode(A3, INPUT); //Courant Q1, Pin 26 sur le 328P
// ----- Timer2 Fast PWM (8-bit), no prescaler -----
TCCR2A = _BV(WGM20) | _BV(WGM21) | _BV(COM2A1) | _BV(COM2B1); // Fast PWM mode, enable PWM on Pin 11, enable PWM on Pin 3
//TCCR2B = _BV(CS20); // No prescaler → 16MHz / 256 = 62.5 kHz
TCCR2B = _BV(CS21); // Prescaler 8 → (16MHz / 8) / 256 = 7.812 kHz
TCCR2A = _BV(WGM20) | _BV(WGM21) | _BV(COM2A1) | _BV(COM2B1);
//TCCR2B = _BV(CS20); // No prescaler → 62.5 kHz
//TCCR2B = _BV(CS21); // Prescaler 8 → 7.81 kHz
TCCR2B = _BV(CS21) | _BV(CS20); // Prescaler 32 → 1.95 kHz
//TCCR2B = _BV(CS22); // Prescaler 64 → 976 Hz
ADCSRA = (1 << ADEN) | (1 << ADPS2); // Set ADC prescaler to 16 (1MHz ADC clock), 13 cycles to read a value so a readout takes 13 uS
// Atmel/Microchip recommends:
// 50–200 kHz for full 10-bit accuracy
// Up to 1 MHz for reduced accuracy (≈ 8–9 bits)
Serial.begin(9600);
}
int currentSense2 = 0;
int currentSense3 = 0;
int countdownOffPWM1 = 1024;
int countdownOffPWM2 = 1024;
uint8_t currentTCNT2 = 0;
uint8_t currentOCR2A = 0;
uint8_t currentOCR2B = 0;
void loop() {
//int adc0 = analogRead(A0);
ADMUX = (1 << REFS0) | (A0 & 0x0F); // Set ADC reference to AVcc and channel to ADC channel 0, example REFS0 = 1 → 0100 0000 | Channel 3 → 0000 0011 | ADMUX → 0100 0011
//int adc0 = analogRead(analogPin1);
ADMUX = (1 << REFS0) | (0 & 0x0F); // Set ADC reference to AVcc and channel to ADC channel 0, example REFS0 = 1 → 0100 0000 | Channel 3 → 0000 0011 | ADMUX → 0100 0011
delayMicroseconds(2);
ADCSRA |= (1 << ADSC); // Start ADC conversion
while (ADCSRA & (1 << ADSC))
; //wait or the ADC conversion to finish
int adc0 = ADC;
//int adc1 = analogRead(A1);
ADMUX = (1 << REFS0) | (A1 & 0x0F); // Set ADC reference to AVcc and channel to ADC channel 0, example REFS0 = 1 → 0100 0000 | Channel 3 → 0000 0011 | ADMUX → 0100 0011
if (adc0 <= 100) {
adc0 = 0;
// Disable PWM output for OC2B
TCCR2A &= ~_BV(COM2B1);
OCR2B = 0; // Optional: also set OCR2B to 0 for consistency;
} else {
// Enable PWM output for OC2B
TCCR2A |= _BV(COM2B1);
uint8_t mappedPWMvalue = map(adc0, 0, 1023, 0, 255);
OCR2B = mappedPWMvalue; // D11, J2 Manette Gauche, Pin 15 sur le 328P, pilote Q3
}
ADMUX = (1 << REFS0) | (1 & 0x0F); // Set ADC reference to AVcc and channel to ADC channel 0, example REFS0 = 1 → 0100 0000 | Channel 3 → 0000 0011 | ADMUX → 0100 0011
delayMicroseconds(2);
ADCSRA |= (1 << ADSC); // Start ADC conversion
while (ADCSRA & (1 << ADSC))
; //wait or the ADC conversion to finish
int adc1 = ADC;
if (adc0 <= 100) { //Because the controller has noise on the ADC reading below this value and we want the cars to be still in position.
adc0 = 0;
}
if (adc1 <= 100) { //Because the controller has noise on the ADC reading below this value and we want the cars to be still in position.
if (adc1 <= 100) {
adc1 = 0;
}
uint8_t pwm1 = map(adc0, 0, 1023, 0, 255);
uint8_t pwm2 = map(adc1, 0, 1023, 0, 255);
if (countdownOffPWM1 == 1024) {
OCR2B = pwm1; // Output is LOW from 0 to pwm1 value (between 0 and 256) and then goes HIGH from pwm1 value to 255 on Pin 3
// Disable PWM output for OC2A
TCCR2A &= ~_BV(COM2A1);
OCR2A = 0; // Optional: also set OCR2A to 0 for consistency
} else {
countdownOffPWM1 = countdownOffPWM1 - 1;
if(countdownOffPWM1 == 0){
countdownOffPWM1 = 1024;
TCCR2A |= _BV(COM2A1); // Reconnect PWM to pin 11
// Enable PWM output for OC2A
TCCR2A |= _BV(COM2A1);
uint8_t mappedPWMvalue = map(adc1, 0, 1023, 0, 255);
OCR2A = mappedPWMvalue; // D3, J4 Manette Millieu Pin 1 sur le 328P, pilote Q1
}
}
if (countdownOffPWM1 == 1024) {
OCR2A = pwm2; // Output on pin 11 TCCR2A |= _BV(COM2B1);
}
else {
countdownOffPWM2 = countdownOffPWM2 - 1;
if(countdownOffPWM2 == 0){
countdownOffPWM2 = 1024;
TCCR2A |= _BV(COM2B1); // Reconnect PWM to pin 3
}
}
if (readADC2) { //Every two cycle we read ADC2 and ADC3
//int adc2 = analogRead(A2);
while (TCNT2 < 217); // wait until timer 2 is 20uS from resetting to perform the ADC conversion in 13 cycles thus in 13uS
ADMUX = (1 << REFS0) | (A2 & 0x0F); // Set ADC reference to AVcc and channel to ADC channel 0, example REFS0 = 1 → 0100 0000 | Channel 3 → 0000 0011 | ADMUX → 0100 0011
ADCSRA |= (1 << ADSC); // Start ADC conversion
while (ADCSRA & (1 << ADSC)); //wait or the ADC conversion to finish
currentSense2 = ADC;
if(currentSense2 > 128){
countdownOffPWM1 = 1023;
TCCR2A &= ~_BV(COM2A1); //Disable PWM from pin 11
PORTB &= ~_BV(PB3); // Pin 11 = PB3, force pin 11 LOW
}
readADC2 = false;
} else {
//int adc2 = analogRead(A3);
while (TCNT2 < 217); // wait until timer 2 is 20uS from resetting to perform the ADC conversion in 13 cycles thus in 13uS
ADMUX = (1 << REFS0) | (A3 & 0x0F); // Set ADC reference to AVcc and channel to ADC channel 0, example REFS0 = 1 → 0100 0000 | Channel 3 → 0000 0011 | ADMUX → 0100 0011
ADCSRA |= (1 << ADSC); // Start ADC conversion
while (ADCSRA & (1 << ADSC)); //wait or the ADC conversion to finish
currentSense3 = ADC;
if(currentSense3 > 128){
countdownOffPWM2 = 1023;
TCCR2A &= ~_BV(COM2B1);; //Disable PWM from pin 3
PORTD &= ~_BV(PD3); // Pin 3 = PD3, force pin 3 LOW
}
readADC2 = true;
}
} //end main loop
Binary file not shown.