На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
  
    > 1-wire на AVR , Tiny13, С++
      Всем привет!

      Нужен мне термостат для роутера - читать температуру и выдавать ШИМ на вентилятор.
      На ардуине все сделал за пару минут, но хочется сделать именно на Tiny13 =)


      Примеры и либы что нашел в инете либо почему-то не работают, либо не помещаются в 13-шку >:(
      Велосипедить не хочется.


      Скиньте пожалуйста рабочий пример/библиотеку для работы с 1-wire на С++.
      Если конкретно - то чтение с DS18B20 на Tiny13.
      Сообщение отредактировано: HardRock -
        Вобщем, в итоге навелосипедил) Только в тиньку 13-ю код не помещается =((( нужно жестко оптимайзить.
          Поботал даташиты и победил таки 1-Wire на тиньке =)


          Может кому пригодится.
          Тест для ATTiny13 на 1 датчик DS18B20.
          Пример читает температуру с датчика и если она выше 40 градусов - запускает PWM (например вентилятор).

          Размер кода - 592 байта.


          Впринципе помещается даже с функцией поиска всех устройств на шине и с выбором нужного устройства.
          Но в этом примере для простоты сделана работа только с одним датчиком.

          ExpandedWrap disabled
            #include <inttypes.h>
            #include <string.h>
            #include <avr/io.h>
            #include <util/delay.h>
            #include <avr/interrupt.h>
             
            // --- Configuration for OneWire
            #define ONEWIRE_PORTReg     PORTB
            #define ONEWIRE_DDRReg      DDRB
            #define ONEWIRE_PINReg      PINB
            #define ONEWIRE_PIN         PB0
             
            // --- Configure for PWM
            #define PWM_PORTReg         PORTB
            #define PWM_DDRReg          DDRB
            #define PWM_PIN             PB1
             
             
            // - Set OneWire pin in Output mode
            #define OneWire_setPinAsOutput  ONEWIRE_DDRReg |= (1<<ONEWIRE_PIN)
             
            // - Set OneWire pin in Input mode
            #define OneWire_setPinAsInput   ONEWIRE_DDRReg &= ~(1<<ONEWIRE_PIN)
             
            // - Set LOW level on OneWire pin
            #define OneWire_writePinLOW     ONEWIRE_PORTReg &=  ~(1<<ONEWIRE_PIN)
             
            // - Set HIGH level on OneWire pin
            #define OneWire_writePinHIGH    ONEWIRE_PORTReg |= (1<<ONEWIRE_PIN)
             
            // - Read level from OneWire pin
            #define OneWire_readPin         ( ( ONEWIRE_PINReg & (1<<ONEWIRE_PIN) ) ? 1 : 0 )
             
             
             
            // - PWM Value ( 0 - off, 255 - max )
            uint8_t PWMValue    = 0;
             
            // - Oveflow counter for PWM
            uint8_t PWMCounter  = 0;
            uint8_t PWM         = 0;
             
             
            //! Calculate CRC-8
            uint8_t crc8(const uint8_t * addr, uint8_t len){
                uint8_t crc = 0;
                while (len--) {
                    uint8_t inbyte = *addr++;
                    for (uint8_t i = 8; i; i--) {
                        uint8_t mix = (crc ^ inbyte) & 0x01;
                        crc >>= 1;
                        if (mix) crc ^= 0x8C;
                        inbyte >>= 1;
                    }
                }
                return crc;
            }
             
            //! Reset function
            uint8_t OneWire_reset(){
                
                // - Wait for line
                uint8_t Retries = 125;
                OneWire_setPinAsInput;
                do{
                    if( --Retries == 0 ) return 0;
                    _delay_us( 2 );
                }while( !OneWire_readPin );
                
                // - Drop line
                OneWire_writePinLOW;
                OneWire_setPinAsOutput;
                _delay_us( 480 );
                
                // - Listen for reply pulse
                OneWire_setPinAsInput;
                _delay_us( 70 );
                
                // - Read line state
                uint8_t State = !OneWire_readPin;
                _delay_us( 410 );
                return State;
            }
             
            //! Write single bit
            void OneWire_writeBit( uint8_t Bit ){
                if( Bit & 1 ){
                    // - Drop line
                    OneWire_writePinLOW;
                    OneWire_setPinAsOutput;
                    // - Write Bit-1
                    _delay_us( 10 );
                    OneWire_writePinHIGH;
                    _delay_us( 55 );
                }else{
                    // - Drop line
                    OneWire_writePinLOW;
                    OneWire_setPinAsOutput;
                    // - Write Bit-0
                    _delay_us( 65 );
                    OneWire_writePinHIGH;
                    _delay_us( 5 );
                }
            }
             
            //! Read single bit
            uint8_t OneWire_readBit(){
                // - Drop line
                OneWire_setPinAsOutput;
                OneWire_writePinLOW;
                _delay_us( 3 );
                
                // - Wait for data
                OneWire_setPinAsInput;
                _delay_us( 10 );
                
                // - Read bit into byte
                uint8_t Bit = OneWire_readPin;
                _delay_us( 53 );
                return Bit;
            }
             
            //! Write byte
            void OneWire_writeByte( const uint8_t Byte, uint8_t Power = 0 ){
                
                // - Write each bit
                for( uint8_t BitMask = 0x01; BitMask; BitMask <<= 1 ) OneWire_writeBit( (BitMask & Byte) ? 1 : 0 );
                
                // - Disable power
                if( !Power ){
                    
                    OneWire_setPinAsInput;
                    OneWire_writePinLOW;
                }
            }
            //! Read byte
            inline uint8_t OneWire_readByte(){
                uint8_t Byte = 0;
                
                // - Read all bits
                for( uint8_t BitMask = 0x01; BitMask; BitMask <<= 1 ){
                    // - Read & store bit into byte
                    if( OneWire_readBit() ) Byte |= BitMask;
                }
                return Byte;
            }
             
             
            //! Read buffer
            inline void OneWire_read( uint8_t * Buffer, uint8_t Size ){
                for( uint8_t i = 0; i < Size; i++ ) Buffer[ i ] = OneWire_readByte();
            }
             
            //! Write buffer
            inline void OneWire_write(const uint8_t * Buffer, uint8_t Size, uint8_t Power = 0 ){
                for( uint8_t i = 0; i < Size; i++ )  OneWire_writeByte(  Buffer[ i ] );
                if( !Power ){
                    // - Disable power
                    OneWire_setPinAsInput;
                    OneWire_writePinLOW;
                }
            }
             
             
            //! Main function
            int main() {
             
                // - Configure PWM pin
                DDRB |= ( 1 << PB1 );
                
                // - Configure timer for PWM
                TIMSK0      = 0b00000010;
                TCCR0B      = 0b00000001;
                
                // - Allow interrupts
                sei();
                
                // - Buffer for ROM
                uint8_t ROM[ 9 ];
                while( 1 ){
                    
                    // - Prepare for new cycle
                    _delay_ms( 1000 );
                    memset( ROM, 0, sizeof( ROM ) );
                    
                    // - Start conversion
                    OneWire_reset();
                    OneWire_writeByte( 0xCC, 1 );
                    OneWire_writeByte( 0x44, 1 );
                    
                    // - Wait until conversion finished
                    _delay_ms( 1000 );
                    
                    // - Read ROM
                    OneWire_reset();
                    OneWire_writeByte( 0xCC, 1 );
                    OneWire_writeByte( 0xBE, 1 );
                    OneWire_read( ROM, sizeof( ROM ) );
                    
                    // - Check ROM CRC
                    if( crc8( ROM, 8 ) != ROM[ 8 ] ){
                        PWMValue = 0;
                        continue;
                    }
                    
                    // --- Get 8-bit temperature
                    // - Construct 16-bit register value from 0 and 1 bytes of ROM.
                    // - Remove float part (4 right bits) to get interger value
                    uint8_t     Temperature     =  ((( ROM[ 1 ] << 8 ) | ROM[ 0 ]) >> 4);
                    
                    
                    if( Temperature < 40 ){
                        PWMValue = 0;
                        continue;
                    }
                    
                    PWMValue = Temperature * 2 - 40;    
                    
                }
             
            }
             
            //! PWM
            ISR( TIM0_OVF_vect ){
                
                // - Set PWM pin HIGH on each PWM counter overflow
                if( ++PWMCounter == 0 ){
                    PWM = PWMValue;
                    PORTB |= (1<<PB1);
                }
                // - Set PWM pin LOW when PWM counter == PWMValue
                if( PWMCounter == PWM ) PORTB &= ~(1<<PB1);
            }


          Добавлено
          Тайминги взяты из 1-Wire библиотеки для Arduino как вероятно, настроенные на практике.
          Тайминге по даташитам как-то не очень работают =)
          Сообщение отредактировано: HardRock -
            Ну могу дать на ассемблере
            Прикреплённый файлПрикреплённый файл1_wire.rar (6,9 Кбайт, скачиваний: 747)
              Цитата HardRock @
              Поботал даташиты и победил таки 1-Wire на тиньке =)


              Может кому пригодится.
              Тест для ATTiny13 на 1 датчик DS18B20.
              Пример читает температуру с датчика и если она выше 40 градусов - запускает PWM (например вентилятор).

              Размер кода - 592 байта.


              Впринципе помещается даже с функцией поиска всех устройств на шине и с выбором нужного устройства.
              Но в этом примере для простоты сделана работа только с одним датчиком.

              ExpandedWrap disabled
                #include <inttypes.h>
                #include <string.h>
                #include <avr/io.h>
                #include <util/delay.h>
                #include <avr/interrupt.h>
                 
                // --- Configuration for OneWire
                #define ONEWIRE_PORTReg     PORTB
                #define ONEWIRE_DDRReg      DDRB
                #define ONEWIRE_PINReg      PINB
                #define ONEWIRE_PIN         PB0
                 
                // --- Configure for PWM
                #define PWM_PORTReg         PORTB
                #define PWM_DDRReg          DDRB
                #define PWM_PIN             PB1
                 
                 
                // - Set OneWire pin in Output mode
                #define OneWire_setPinAsOutput  ONEWIRE_DDRReg |= (1<<ONEWIRE_PIN)
                 
                // - Set OneWire pin in Input mode
                #define OneWire_setPinAsInput   ONEWIRE_DDRReg &= ~(1<<ONEWIRE_PIN)
                 
                // - Set LOW level on OneWire pin
                #define OneWire_writePinLOW     ONEWIRE_PORTReg &=  ~(1<<ONEWIRE_PIN)
                 
                // - Set HIGH level on OneWire pin
                #define OneWire_writePinHIGH    ONEWIRE_PORTReg |= (1<<ONEWIRE_PIN)
                 
                // - Read level from OneWire pin
                #define OneWire_readPin         ( ( ONEWIRE_PINReg & (1<<ONEWIRE_PIN) ) ? 1 : 0 )
                 
                 
                 
                // - PWM Value ( 0 - off, 255 - max )
                uint8_t PWMValue    = 0;
                 
                // - Oveflow counter for PWM
                uint8_t PWMCounter  = 0;
                uint8_t PWM         = 0;
                 
                 
                //! Calculate CRC-8
                uint8_t crc8(const uint8_t * addr, uint8_t len){
                    uint8_t crc = 0;
                    while (len--) {
                        uint8_t inbyte = *addr++;
                        for (uint8_t i = 8; i; i--) {
                            uint8_t mix = (crc ^ inbyte) & 0x01;
                            crc >>= 1;
                            if (mix) crc ^= 0x8C;
                            inbyte >>= 1;
                        }
                    }
                    return crc;
                }
                 
                //! Reset function
                uint8_t OneWire_reset(){
                    
                    // - Wait for line
                    uint8_t Retries = 125;
                    OneWire_setPinAsInput;
                    do{
                        if( --Retries == 0 ) return 0;
                        _delay_us( 2 );
                    }while( !OneWire_readPin );
                    
                    // - Drop line
                    OneWire_writePinLOW;
                    OneWire_setPinAsOutput;
                    _delay_us( 480 );
                    
                    // - Listen for reply pulse
                    OneWire_setPinAsInput;
                    _delay_us( 70 );
                    
                    // - Read line state
                    uint8_t State = !OneWire_readPin;
                    _delay_us( 410 );
                    return State;
                }
                 
                //! Write single bit
                void OneWire_writeBit( uint8_t Bit ){
                    if( Bit & 1 ){
                        // - Drop line
                        OneWire_writePinLOW;
                        OneWire_setPinAsOutput;
                        // - Write Bit-1
                        _delay_us( 10 );
                        OneWire_writePinHIGH;
                        _delay_us( 55 );
                    }else{
                        // - Drop line
                        OneWire_writePinLOW;
                        OneWire_setPinAsOutput;
                        // - Write Bit-0
                        _delay_us( 65 );
                        OneWire_writePinHIGH;
                        _delay_us( 5 );
                    }
                }
                 
                //! Read single bit
                uint8_t OneWire_readBit(){
                    // - Drop line
                    OneWire_setPinAsOutput;
                    OneWire_writePinLOW;
                    _delay_us( 3 );
                    
                    // - Wait for data
                    OneWire_setPinAsInput;
                    _delay_us( 10 );
                    
                    // - Read bit into byte
                    uint8_t Bit = OneWire_readPin;
                    _delay_us( 53 );
                    return Bit;
                }
                 
                //! Write byte
                void OneWire_writeByte( const uint8_t Byte, uint8_t Power = 0 ){
                    
                    // - Write each bit
                    for( uint8_t BitMask = 0x01; BitMask; BitMask <<= 1 ) OneWire_writeBit( (BitMask & Byte) ? 1 : 0 );
                    
                    // - Disable power
                    if( !Power ){
                        
                        OneWire_setPinAsInput;
                        OneWire_writePinLOW;
                    }
                }
                //! Read byte
                inline uint8_t OneWire_readByte(){
                    uint8_t Byte = 0;
                    
                    // - Read all bits
                    for( uint8_t BitMask = 0x01; BitMask; BitMask <<= 1 ){
                        // - Read & store bit into byte
                        if( OneWire_readBit() ) Byte |= BitMask;
                    }
                    return Byte;
                }
                 
                 
                //! Read buffer
                inline void OneWire_read( uint8_t * Buffer, uint8_t Size ){
                    for( uint8_t i = 0; i < Size; i++ ) Buffer[ i ] = OneWire_readByte();
                }
                 
                //! Write buffer
                inline void OneWire_write(const uint8_t * Buffer, uint8_t Size, uint8_t Power = 0 ){
                    for( uint8_t i = 0; i < Size; i++ )  OneWire_writeByte(  Buffer[ i ] );
                    if( !Power ){
                        // - Disable power
                        OneWire_setPinAsInput;
                        OneWire_writePinLOW;
                    }
                }
                 
                 
                //! Main function
                int main() {
                 
                    // - Configure PWM pin
                    DDRB |= ( 1 << PB1 );
                    
                    // - Configure timer for PWM
                    TIMSK0      = 0b00000010;
                    TCCR0B      = 0b00000001;
                    
                    // - Allow interrupts
                    sei();
                    
                    // - Buffer for ROM
                    uint8_t ROM[ 9 ];
                    while( 1 ){
                        
                        // - Prepare for new cycle
                        _delay_ms( 1000 );
                        memset( ROM, 0, sizeof( ROM ) );
                        
                        // - Start conversion
                        OneWire_reset();
                        OneWire_writeByte( 0xCC, 1 );
                        OneWire_writeByte( 0x44, 1 );
                        
                        // - Wait until conversion finished
                        _delay_ms( 1000 );
                        
                        // - Read ROM
                        OneWire_reset();
                        OneWire_writeByte( 0xCC, 1 );
                        OneWire_writeByte( 0xBE, 1 );
                        OneWire_read( ROM, sizeof( ROM ) );
                        
                        // - Check ROM CRC
                        if( crc8( ROM, 8 ) != ROM[ 8 ] ){
                            PWMValue = 0;
                            continue;
                        }
                        
                        // --- Get 8-bit temperature
                        // - Construct 16-bit register value from 0 and 1 bytes of ROM.
                        // - Remove float part (4 right bits) to get interger value
                        uint8_t     Temperature     =  ((( ROM[ 1 ] << 8 ) | ROM[ 0 ]) >> 4);
                        
                        
                        if( Temperature < 40 ){
                            PWMValue = 0;
                            continue;
                        }
                        
                        PWMValue = Temperature * 2 - 40;    
                        
                    }
                 
                }
                 
                //! PWM
                ISR( TIM0_OVF_vect ){
                    
                    // - Set PWM pin HIGH on each PWM counter overflow
                    if( ++PWMCounter == 0 ){
                        PWM = PWMValue;
                        PORTB |= (1<<PB1);
                    }
                    // - Set PWM pin LOW when PWM counter == PWMValue
                    if( PWMCounter == PWM ) PORTB &= ~(1<<PB1);
                }


              Добавлено
              Тайминги взяты из 1-Wire библиотеки для Arduino как вероятно, настроенные на практике.
              Тайминге по даташитам как-то не очень работают =)

              Увидел ваш вариант работы с 1-Wire, он действительно работает, попробовал для Atmega8
              у вас только одна ошибка вот здесь, пропущен выделенный фрагмент
              Скрытый текст

              //! Write buffer
              inline void OneWire_write(const uint8_t * Buffer, uint8_t Size, uint8_t Power = 0 ){
              for( uint8_t i = 0; i < Size; i++ ) OneWire_writeByte( Buffer[ i ], Power );
              if( !Power ){
              // - Disable power
              OneWire_setPinAsInput;
              OneWire_writePinLOW;
              }
              }
                Да, есть такое.
                На работу это не влияет т.к. определено значение по умолчанию для этой пременной :D
                  Цитата HardRock @
                  Да, есть такое.
                  На работу это не влияет т.к. определено значение по умолчанию для этой пременной :D

                  Просто в эту функцию OneWire_writeByte должно же передаваться 2 параметра, а передаётся только один на что компилятор и ругался. :D
                  Ещё хочу спросить как оптимально полученный результат в uint8_t Temperature перевести в char для вывода на дисплей от нокии 1202, Использую библиотеку отсюда http://digitalchip.ru/podklyuchenie-disple...-2660-2760-6085 в ней есть 3 функции вывода на дисплей

                  void nlcd_Print(char * message);
                  void nlcd_PrintF(unsigned char * message);
                  void nlcd_Putc(unsigned char c);

                  пробовал в 2 первых выводить
                  nlcd_GotoXY(0,3); // третья строка
                  nlcd_PrintF((unsigned int)Temperature);
                  получается абракадабра
                  сделал так
                  ExpandedWrap disabled
                    ...
                        PWMValue = Temperature; // * 2; // - 40;
                     
                        buffer2[0]=PWMValue % 10;
                        PWMValue/=10;
                        buffer2[1]=PWMValue % 10;
                        PWMValue/=10;
                        buffer2[2]=PWMValue % 10;
                        PWMValue/=10;
                        buffer2[3]=PWMValue % 10;
                            nlcd_GotoXY(4,4);
                            nlcd_Putc(0x30+buffer2[3]);
                            nlcd_GotoXY(5,4);
                            nlcd_Putc(0x30+buffer2[2]);
                            nlcd_GotoXY(6,4);
                            nlcd_Putc(0x30+buffer2[1]);
                            nlcd_GotoXY(7,4);
                            nlcd_Putc(0x30+buffer2[0]);

                  но как-то коряво выглядит, так как этот не соответствует теме, чтобы модератор не ругал, ответ можно в личные сообщения отправлять.
                    Значение с датчика - это число, сколько фактически градусов цельсия. Экран принимает символы по таблице ASCII.
                    Для перевода в числа в строку нужно использовать функцию itoa http://www.cplusplus.com/reference/cstdlib/itoa/

                    Её скорее всего у тебя не будет, и то что напсал ты - это по сути та самая itoa().
                    которая может выглядеть как-то так:

                    ExpandedWrap disabled
                      char* itoa(int val, int base){
                          static char buf[32] = {0};
                       
                          int i = 30;
                          
                          for(; val && i ; --i, val /= base) buf[i] = "0123456789abcdef"[val % base];
                          
                          return &buf[i+1];
                          
                      }


                    В интернете куча вариантов этой функции как "стандартных" из системных библиотек, так и альтернативных, как вариант выше.

                    Добавлено
                    Цитата BigallS @
                    Просто в эту функцию OneWire_writeByte должно же передаваться 2 параметра, а передаётся только один на что компилятор и ругался.


                    Просто ты видимо пользуешься С компилятором, а я писал под C++, там есть значения по умолчанию. (AVR-GCC)


                    Кстати, прошивка, которая сейчас работает на железе:
                    ExpandedWrap disabled
                      #include <inttypes.h>
                      #include <string.h>
                      #include <avr/io.h>
                      #include <util/delay.h>
                      #include <avr/interrupt.h>
                       
                      // --- Configuration for OneWire
                      #define ONEWIRE_PORTReg     PORTB
                      #define ONEWIRE_DDRReg      DDRB
                      #define ONEWIRE_PINReg      PINB
                      #define ONEWIRE_PIN         PB0
                       
                      // --- Configure for PWM (fan)
                      #define PWM_PORTReg         PORTB
                      #define PWM_DDRReg          DDRB
                      #define PWM_PIN             PB1
                       
                      // - Minimal temperature to activate fan
                      #define FAN_MIN_TEMPERATURE 40
                       
                      // - Temperature for maximum fan power
                      #define FAN_MAX_TEMPERATURE 70
                       
                      // - Power, used to start fan. Must be enough to start!
                      #define FAN_START_PWM_VALUE 200
                      #define FAN_START_TIME      2000
                       
                      // - Minimal fan power
                      #define FAN_MIN_POWER       60
                       
                      // - Maximal fan power
                      #define FAN_MAX_POWER       255
                       
                      // - Configure for alarm
                      #define ALARM_PORTReg               PORTB
                      #define ALARM_DDRReg                DDRB
                      #define ALARM_PIN                   PB2
                       
                      #define ALARM_ON_MAX_ERRORS         16
                      #define ALARM_ON_MAX_TEMPERATURE    80
                       
                       
                       
                      // - Set OneWire pin in Output mode
                      #define OneWire_setPinAsOutput  ONEWIRE_DDRReg |= (1<<ONEWIRE_PIN)
                       
                      // - Set OneWire pin in Input mode
                      #define OneWire_setPinAsInput   ONEWIRE_DDRReg &= ~(1<<ONEWIRE_PIN)
                       
                      // - Set LOW level on OneWire pin
                      #define OneWire_writePinLOW     ONEWIRE_PORTReg &=  ~(1<<ONEWIRE_PIN)
                       
                      // - Set HIGH level on OneWire pin
                      #define OneWire_writePinHIGH    ONEWIRE_PORTReg |= (1<<ONEWIRE_PIN)
                       
                      // - Read level from OneWire pin
                      #define OneWire_readPin         ( ( ONEWIRE_PINReg & (1<<ONEWIRE_PIN) ) ? 1 : 0 )
                       
                       
                      // - Turn on alarm
                      #define Alarm_On    ALARM_PORTReg |= (1<<ALARM_PIN);
                       
                      // - Turn off alarm
                      #define Alarm_Off   ALARM_PORTReg &= ~(1<<ALARM_PIN);
                       
                      // - PWM Value ( 0 - off, 255 - max )
                      uint8_t PWMValue    = 0;
                       
                      // - Oveflow counter for PWM
                      uint8_t PWMCounter  = 0;
                      uint8_t PWM         = 0;
                       
                       
                      //! Calculate CRC-8
                      uint8_t crc8(const uint8_t * addr, uint8_t len){
                          uint8_t crc = 0;
                          while (len--) {
                              uint8_t inbyte = *addr++;
                              for (uint8_t i = 8; i; i--) {
                                  uint8_t mix = (crc ^ inbyte) & 0x01;
                                  crc >>= 1;
                                  if (mix) crc ^= 0x8C;
                                  inbyte >>= 1;
                              }
                          }
                          return crc;
                      }
                       
                      //! Reset function
                      uint8_t OneWire_reset(){
                          
                          // - Wait for line
                          uint8_t Retries = 125;
                          OneWire_setPinAsInput;
                          do{
                              if( --Retries == 0 ) return 0;
                              _delay_us( 2 );
                          }while( !OneWire_readPin );
                          
                          // - Drop line
                          OneWire_writePinLOW;
                          OneWire_setPinAsOutput;
                          _delay_us( 480 );
                          
                          // - Listen for reply pulse
                          OneWire_setPinAsInput;
                          _delay_us( 70 );
                          
                          // - Read line state
                          uint8_t State = !OneWire_readPin;
                          _delay_us( 410 );
                          return State;
                      }
                       
                      //! Write single bit
                      void OneWire_writeBit( uint8_t Bit ){
                          if( Bit & 1 ){
                              // - Drop line
                              OneWire_writePinLOW;
                              OneWire_setPinAsOutput;
                              // - Write Bit-1
                              _delay_us( 10 );
                              OneWire_writePinHIGH;
                              _delay_us( 55 );
                          }else{
                              // - Drop line
                              OneWire_writePinLOW;
                              OneWire_setPinAsOutput;
                              // - Write Bit-0
                              _delay_us( 65 );
                              OneWire_writePinHIGH;
                              _delay_us( 5 );
                          }
                      }
                       
                      //! Read single bit
                      uint8_t OneWire_readBit(){
                          // - Drop line
                          OneWire_setPinAsOutput;
                          OneWire_writePinLOW;
                          _delay_us( 3 );
                          
                          // - Wait for data
                          OneWire_setPinAsInput;
                          _delay_us( 10 );
                          
                          // - Read bit into byte
                          uint8_t Bit = OneWire_readPin;
                          _delay_us( 53 );
                          return Bit;
                      }
                       
                      //! Write byte
                      inline void OneWire_writeByte( const uint8_t Byte, uint8_t Power = 0 ){
                          
                          // - Write each bit
                          for( uint8_t BitMask = 0x01; BitMask; BitMask <<= 1 ) OneWire_writeBit( (BitMask & Byte) ? 1 : 0 );
                          
                          // - Disable power
                          if( !Power ){
                              OneWire_setPinAsInput;
                              OneWire_writePinLOW;
                          }
                      }
                      //! Read byte
                      inline uint8_t OneWire_readByte(){
                          uint8_t Byte = 0;
                          
                          // - Read all bits
                          for( uint8_t BitMask = 0x01; BitMask; BitMask <<= 1 ){
                              // - Read & store bit into byte
                              if( OneWire_readBit() ) Byte |= BitMask;
                          }
                          return Byte;
                      }
                       
                       
                      //! Read buffer
                      inline void OneWire_read( uint8_t * Buffer, uint8_t Size ){
                          for( uint8_t i = 0; i < Size; i++ ) Buffer[ i ] = OneWire_readByte();
                      }
                       
                      //! Write buffer
                      inline void OneWire_write(const uint8_t * Buffer, uint8_t Size, uint8_t Power = 0 ){
                          for( uint8_t i = 0; i < Size; i++ )  OneWire_writeByte(  Buffer[ i ] );
                          if( !Power ){
                              // - Disable power
                              OneWire_setPinAsInput;
                              OneWire_writePinLOW;
                          }
                      }
                       
                      //! Map one range to another
                      uint16_t map( uint16_t x, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max){
                        return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
                      }
                       
                       
                      //! Main function
                      int main() {
                          
                          // - Configure alarm pin
                          ALARM_DDRReg |= ( 1 << PB2 );
                          
                          // - Configure PWM pin
                          PWM_DDRReg |= ( 1 << PB1 );
                          
                          // - Configure timer for PWM
                          TIMSK0      = 0b00000010;
                          TCCR0B      = 0b00000001;
                          
                          // - Allow interrupts
                          sei();
                          
                          // - Buffer for ROM
                          uint8_t ROM[ 9 ];
                          
                          // - Fan state
                          uint8_t FanState    = 0;
                          
                          // - Error count
                          uint8_t ErrorCount  = 0;
                          
                          // - Main loop
                          while( 1 ){
                              // - Check error count
                              if( ErrorCount >= ALARM_ON_MAX_ERRORS ){
                                  // - Force start fan at 100% power
                                  PWMValue    = 255;
                                  FanState    = 1;
                                  ErrorCount  = 0;
                                  // - Turn on alarm pin
                                  Alarm_On;
                              }
                              
                              // - Prepare for new cycle
                              _delay_ms( 500 );
                              memset( ROM, 0, sizeof( ROM ) );
                              
                              // - Start conversion
                              if( !OneWire_reset() ){
                                  // - Report error
                                  ErrorCount++;
                                  continue;
                              }
                              OneWire_writeByte( 0xCC, 1 );
                              OneWire_writeByte( 0x44, 1 );
                              
                              // - Wait until conversion finished
                              _delay_ms( 1000 );
                              
                              // - Read ROM
                              if( !OneWire_reset() ){
                                  // - Report error
                                  ErrorCount++;
                                  continue;
                              }
                              OneWire_writeByte( 0xCC, 1 );
                              OneWire_writeByte( 0xBE, 1 );
                              OneWire_read( ROM, sizeof( ROM ) );
                              
                              // - Check ROM CRC
                              if( crc8( ROM, 8 ) != ROM[ 8 ] ){
                                  // - Report error
                                  ErrorCount++;
                                  continue;
                              }
                              // ------------------------------------------------------------------
                              // - Reset error count & turn alarm off
                              ErrorCount = 0;
                              Alarm_Off;
                              // ------------------------------------------------------------------
                              
                              // --- Get 8-bit temperature
                              // - Construct 16-bit register value from 0 and 1 bytes of ROM.
                              // - Remove float part (4 right bits) to get interger value
                              uint8_t     Temperature     = ((( ROM[ 1 ] << 8 ) | ROM[ 0 ]) >> 4 );
                              
                              // - Disable fan when temperature lower than 40* celsius
                              if( Temperature < FAN_MIN_TEMPERATURE ){
                                  // - Stop fan
                                  PWMValue = 0;
                                  FanState = 0;
                                  continue;
                              }
                              
                              // - Start fan if stopped
                              if( !FanState ){
                                  PWMValue = FAN_START_PWM_VALUE;
                                  _delay_ms( FAN_START_TIME );
                                  FanState = 1;
                              }
                              
                       
                              // - Alarm if overheated
                              if( Temperature > ALARM_ON_MAX_TEMPERATURE ){
                                  
                                  // - Turn alarm on
                                  Alarm_On;
                                  _delay_ms( 100 );
                                  
                                  // - Turn alarm off
                                  Alarm_Off;
                              }
                       
                              // - Set fan power
                              uint16_t Power = map( Temperature,
                                  FAN_MIN_TEMPERATURE,    FAN_MAX_TEMPERATURE,
                                  FAN_MIN_POWER,          FAN_MAX_POWER
                              );
                              
                              // - Limit power to max PWM
                              if( Power > 255 ) Power = 255;
                              
                              // - Set fan power
                              PWMValue = Power;
                              
                          }
                       
                      }
                       
                      //! PWM
                      ISR( TIM0_OVF_vect ){
                          
                          // - Set PWM pin HIGH on each PWM counter overflow
                          if( ++PWMCounter == 0 ){
                              PWM = PWMValue;
                              PWM_PORTReg |= (1<<PWM_PIN);
                          }
                          
                          // - Set PWM pin LOW when PWM counter == PWMValue
                          if( PWMCounter == PWM ) PWM_PORTReg &= ~(1<<PWM_PIN);
                      }


                    Добавлено
                    Тут если нет показаний с датчика некоторе время, то вентилятор включается на полную, плюс светодиод извещает о перегреве своим миганием. Скорость вентилятора регулируется пропорционально температуре.
                    Плюс есть "раскрутка" вентилятора при включении (иначе из остановленного состояния невозможно включить на минимальные обороты, не хватит мощности)
                    Сообщение отредактировано: HardRock -
                      Спасибо, по выводу строки теперь понятно.
                      Я пишу на Atmel Studio 6, по умолчанию проект на С.
                        Простите, а "плюсЫ"-то где? Кроме значения параметра по умолчанию ничего другого от С++ я в этом исходнике не вижу... И есть еще пути для оптимизации - если внимательно посмотреть на картинки чтения и записи бита то можно увидеть, что две функции (чтения и записи бита) можно фактически заменить на одну "обмен битом". Аналогично и функции чтения/записи байта заменяются на одну - "обмен байтом". Для чтения передаем 0xFF и используем результат, для записи - передаем что надо и результат игнорируем.
                        Примерно так:
                        ExpandedWrap disabled
                          uint8_t one_wire::exchange(uint8_t data)
                          {
                              PORTC &= ~BIT_MASK;
                              uint8_t Counter = 8;
                              do
                              {
                                  bool Result = exchange_bit(data & (1<<0));
                                  data  = Result ? (data >> 1) | (1 << 7) : data >> 1;
                              }
                              while (--Counter);
                              PORTC |= BIT_MASK;
                              return data;
                          }
                           
                          inline bool one_wire::exchange_bit(bool data)
                          {
                              DDRC |= BIT_MASK;
                              _delay_us(7);
                              if(data)
                                  DDRC &= ~BIT_MASK;
                              _delay_us(8);
                              data = PINC & BIT_MASK;
                              _delay_us(45);
                              DDRC &= ~BIT_MASK;
                              _delay_us(1);
                              return data;
                          }
                          ...совсем маленький термостат на тиньке-26 http://arv.radioliga.com/content/view/152/44/
                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0473 ]   [ 18 queries used ]   [ Generated: 16.04.24, 13:05 GMT ]