El circuito de luz intermitente AVR de LED impulsado por MOSFET exhibe un comportamiento desagradable

1

El siguiente circuito, construido en un prototypeboard / stripboard, a veces no funciona: está muerto para el mundo. No hay salida independientemente de la entrada. Originalmente pensé que algunas de las conexiones soldadas eran inestables (debido al hecho de que al tocar la placa parecería que el circuito se apagaba o volvía a estar vivo), sin embargo, después de revisar la placa prototipo nuevamente, no pude. encuentra mucho de algo fuera de lo común, aparte de la resistencia entre Vcc y Gnd siendo 7. mega ohmios Me pregunto ahora si hay algún error en el diseño / lógica del circuito.

Laentradaes0Vo12V,yestáconectadaalauCatravésdeloptoacoplador.LaunidaduCescuchalaentradayparpadealosdistintosledsmientraslaentradaesde12Vyladesactivacuandolaentradavuelvea0V.Códigocompleto:

#include<avr/io.h>#include<util/delay.h>#include<avr/interrupt.h>#include<avr/cpufunc.h>#include<avr/sleep.h>volatileuint8_tuseless=0;ISR(INT0_vect){useless^=0xFF;}intmain(void){//UsingPCINT0aslow-levelinterruptMCUCR&=~((1<<ISC01)|(1<<ISC00));//lowlevelinterruptonINT0GIMSK=1<<INT0;//enableINT0interrupt#defineOUTPUTA4#defineOUTPUTB3#defineINPUT1DDRB=0x00|(1<<OUTPUTA)|(1<<OUTPUTB);PORTB=0;sei();//enableinterrupts_NOP();while(1){if((PINB&&(1<<INPUT))==0){PORTB|=(1<<OUTPUTA)|(1<<OUTPUTB);while((PINB&(1<<INPUT))==0){_delay_ms(170);PORTB^=(1<<OUTPUTA);}PORTB&=~((1<<OUTPUTA)|(1<<OUTPUTB));}if(1){//GotosleepMCUCR|=1<<SE;MCUCR=MCUCR&&~((1<<SM1)|(1<<SM1))|(1<<SM1)|(0<<SM1);sleep_cpu();//WakeuphereMCUCR&=~(1<<SE);}

Mimejorideaactualesreponerel74HC14N(disculpas,eldisparadorSchmitteseso,ynoel74LS14),yeltamañodelatapadederivaciónmáspequeña(elcircuitosealimentadeunwallwartde2-3AyhaybastantepocosLEDs)

EDITAR:sehacorregidoelesquemafrentealasalidadeloptoacoplador(gracias Peter Benett )

EDIT2 Se ha corregido el esquema para mostrar que el pin de reinicio está vinculado a Vcc (gracias geometrikal )

    
pregunta angelatlarge

3 respuestas

1

Parece que hay una confusión entre el operador AND bit a bit & y el operador AND lógico &&

Por ejemplo, esta línea en su código

if ( (PINB && (1<<INPUT)) == 0 ) 

no se convierte en verdadero solo cuando bit1 del puerto B se convierte en alto, pero cuando cualquiera de los bits es alto. Eso sucede porque (1<<INPUT) es > 0, por lo que siempre es verdadero y eso deja el cheque en PINB, será cierto con 0x01 o 0x02 o 0x03 ... 0xff

La forma correcta de verificar el estado de PB1 es

if ( (PINB & (1<<INPUT)) == 0 ) 

Otro lugar donde usas el operador equivocado es

MCUCR = MCUCR && ~( (1<<SM1)|(1<<SM1) ) |  (1<<SM1)|(0<<SM1);

Eso da como resultado 0 o 1, lo que deberías usar es

MCUCR = MCUCR & ~( (1<<SM1)|(1<<SM1) ) |  (1<<SM1)|(0<<SM1);

Llegando a su circuito real, ¿cuál es la necesidad de 74LS14?
Todo lo que necesita es habilitar el pull-up interno para PB1 y conectar el colector opto-transistor al pin del puerto para bajarlo cuando esté activo.

Solo puedes conectarlo como

Y en cuanto al código, algo como

// change the following clock frequency depending on the clock you use
#define F_CPU 9600000UL // 9.6 MHz'
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include <avr/cpufunc.h>
#include <avr/sleep.h>

#define OUTPUTA 4
#define OUTPUTB 3
#define INPUT   1

volatile uint8_t  useless = 0;
volatile uint8_t  flashing_enable = 0;

ISR(INT0_vect)
{
    if((PINB & (1 << INPUT)) == 0)
    {
        flashing_enable = 1; // set flashing flag
        PORTB |= (1 << OUTPUTA) | (1 << OUTPUTB); // turn on both leds
    }
    else
    {
        flashing_enable = 0; // clear flashing flag
    }
}


int main(void)
{
    DDRB = 0x00 | (1 << OUTPUTA) | (1 << OUTPUTB);
    PORTB = (1 << INPUT); // enable pullup
    // External Interrupt(s) initialization
    // INT0: On
    // INT0 Mode: Any change
    // Interrupt on any change on pins PCINT0-5: Off
    GIMSK = (1 << INT0) | (0 << PCIE);
    MCUCR = (0 << ISC01) | (1 << ISC00);
    GIFR = (1 << INTF0) | (0 << PCIF);
    GIFR = (0 << INTF0) | (1 << PCIF);
    sei();    // enable interrupts

    while(1)
    {
        if(flashing_enable)
        {
            _delay_ms(170);
            PORTB ^= (1 << OUTPUTA);
        }
        else
        {
            PORTB &= ~((1 << OUTPUTA) | (1 << OUTPUTB));
        }
    }
}

He utilizado leds individuales solo para mostrar el esquema de conexión genérico. También he omitido los condensadores, agrégalos a tu hardware real.

    
respondido por el alexan_e
0

La entrada al 74LS14 (pin 1) está vinculada a +5 voltios, por lo que cualquier entrada a través del optoacoplador no tendrá ningún efecto.

Movería R2 para conectar entre + 5V y el pin 1 de 74LS14, con el pin 1 también conectado al colector óptico y el emisor de opto conectado a tierra. Eso permitirá que el opto controle la entrada al 74LS14.

    
respondido por el Peter Bennett
0

Además de los problemas mencionados en la respuesta anterior, esta línea:

MCUCR &= ~ ( (1<<ISC01)|(1<<ISC00) );   // low level interrupt on INT0

También es bastante incorrecto: no estoy seguro de por qué decidí invertir el valor cargado en MCUCR

Después de agregar un límite a la línea de restablecimiento (Gracias @ Andy aka ), corrigiendo los errores de codificación y cambiando a una interrupción de bajo nivel de interrupción de bajo nivel (ambas señaladas por alexan_e ), la luz intermitente parece estar bien. Mantuve la función de dormir.

    
respondido por el angelatlarge

Lea otras preguntas en las etiquetas