Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- FILE .......................... S_DRYER_2.C
- DATE ....................... 21-3-18
- CONTENT
- All code for simple dryer started November 2107
- S_DRYER_2.C for 1st off pcb
- Processor TINY44A
- FUSES E4 DE FF
- No clock division
- No clock output
- SUT1 1
- SUT0 0
- CLOCK 128Khz
- Brown Out 1.8 Volts
- HARDWARE USAGE
- TIMER 1 (8 bit) ....................... Timing
- TIMER 0 ............................ Generate alarm drive frequency
- DIP pinning
- PIn 1 ..... Vcc
- Pin 2 ..... PB0 .................................. Green LED
- Pin 3 ..... PB1 ................................... Motor drive
- Pin 4 ..... PB3 /RESET ....................... Programming
- Pin 5 ..... PB2 / OC0A ....................... Audio Alarm drive
- Pin 6 ..... PA7 ................................... Power latch
- PIn 7 ..... PA6 / MOSI ...................... DIL SW , Programming.
- Pin 8 ..... PA5 / MISO ....................... Programming, 'test mode' rig detection
- Pin 9 ..... PA4 / UCLK ........................ DIL SW , Programming and data output
- Pin 10 ..... PA3 ..................................... Used as SS for SPI output , ' logging' detection
- Pin 11 ..... PA2 / ADC2 ......................... Cam sensor
- Pin 12 ..... PA1 /ADC1 .......................... Battery voltage
- Pin 13 ...... PA0 / AREF ....................... reference diode for A-D use
- Pin 14 ...... GRND
- */
- #include "TINY44.H" // bits included in this header
- #include "STDLIB.H"
- #include "STDIO.H"
- #include "DELAY.H"
- #include "MATH.H"
- #define FALSE 0
- #define TRUE !FALSE
- #define _ALTERNATE_PUTCHAR_ // lib function replaced, op goes to SPI
- #define OSC 128000 // low freq internal osc
- #define PRESCALE 1 // for timer 0
- #define PRESCALE_BITS 0x01 // no prescale ie 1 0x02 // to give prescale of 8
- #define DEF_MOTOR_TIME 30 // 1/10 seconds for cam to get beyond switch
- #define SHUTDOWNTIME 420 // seconds after flow/pressure switch opens before power removed
- #define MOTOR_TIMEOUT 5 // seconds max time motor on for
- #define BAT_LIM 250 // 1/100 volts battery at end of life
- #define SWITCH_LIM 100 // 1/100 volts below this means swich open
- #define R1 100 // K ohms potential divider for battery volts
- #define R2 47 // K ohms potentaial divider for battery volts
- #define ADCFSD 1024
- #define VREF 122 // units 1/100 volts
- #define BATCHAN 0x01 // ADC1 used for measuring battery voltage
- #define POWER_LATCH PORTA.7
- #define POWER_ON 1
- #define POWER_OFF 0
- #define GREEN_LED PORTB.0
- #define LED_ON 0
- #define LED_OFF 1
- #define ALARM_ON 0
- #define ALARM_OFF !ALARM_ON
- #define MOTOR_DRIVE PORTB.1
- #define MOTOR_PIN PINB.1
- #define MOTOR_ON 1
- #define MOTOR_OFF 0
- #define CAM_SW PINA.2
- #define CAM_INTROUGH 1 // cam switch open ie. in the trough in the cam
- #define SW_CLOSED 0
- #define SW_OPEN !SW_CLOSED
- #define SS_LINE PORTA.3
- #define SPI_CLK PORTA.4
- #define SPI_DO PORTA.6
- #define MOTOR_FAULT 0x01
- #define BATTERY_FAULT 0x02
- #define INITIAL_BLEEP 0x80 // artificial 'fault' to cause alarm to sound at power up
- // Functions
- void readlinks(void); // for setting switching speed between dryer canisters returns seconds
- int getbatvolts(void); // returns in units of 1/100 volts
- void inithw(void); // set internal registers
- void txheader(void); // send useful ident stuff to terminal
- void init_soft_spi(void); // change port pins used for links and SPI to outputs
- void resurrectdog(void); // reset watchdog timer to 8 secs
- void alarm(char control); // control takes either ALARM_ON or ALARM_OFF
- void disable_spipins(); // all to inputs with no pull ups
- // Global variables
- int speedtable[8][2] = // seconds selected by links cycle_reload , shutdown time links decimal
- {
- {5,10}, // both dil sws on in test mode 000 0
- {10,20}, // sw1 off sw2 on in test mode 001 2
- {1800,3600}, // both dil sws on normal mode 010 4
- {3600,7200}, // dil sw 1 off dil sw 2 on normal 011 6
- {15,30}, // dil sw 1 off dilsw 2 off test 100 8
- {20,40}, // dilsw 1 off dil sw 2 off test 101 10
- {7200, 14400}, // dil sw 1 on ,dilsw 2 off normal 110 12
- {14400,14400}, // dil sw 1 off ,dilsw 2 off normal 111 14
- };
- char tenthsecs; // increments 0-9
- char seconds; // increments on close to 1 second interval
- char motor_timer; // for detecting stalled motor
- int cycletime_reload; // seconds set by which links fitted
- int cycletime; // timer that is actually used
- int shutdown_time; // seconds after flow stops before sytem powers down set by links
- int timeout; // timing for removing power after no flow/pressure
- char print_timer;
- char links; // only used for printing state of links
- char fault; // bit mapped for different faults
- bit switchstate; // monitors flow/pressure switch by measuring voltage
- bit datalogging; // controlled by inverse of state of SS line at power on, when set data sent out to SPI
- bit testing; // controlled by inverse of state of MISO line at power on, when set use test values for cycle time
- //**************************************************************************************
- interrupt[TIM1_OVF] void timer0(void) // 1Mhz clock prescale 8 overflow rate 488 per sec
- //128 KHz prescale 1 overflow rate 250 per sec because
- // in 8 bit phase correct mode
- // execution time approx 150 to 250 microsec at 128KHz OSC
- {
- static int count =OSC/256/PRESCALE/10/2;
- if(--count == 0)
- {
- count = OSC/256/PRESCALE/10/2;
- if(++tenthsecs == 10)
- {
- GREEN_LED = LED_ON;
- tenthsecs = 0;
- ++seconds;
- print_timer++;
- if(cycletime) cycletime--;
- if(motor_timer) motor_timer--;
- if( switchstate == SW_OPEN && timeout) timeout--;
- if(seconds < 13 && fault & seconds || fault & INITIAL_BLEEP) alarm(ALARM_ON);
- else alarm(ALARM_OFF);
- GREEN_LED = LED_OFF;
- }
- }
- }
- //*************************************************
- void main(void)
- {
- char localsecs =5;
- int batvolts; // units 1/100 volts measured voltage
- char timetoprint = 10; // keep compiler happy
- inithw();
- resurrectdog(); // set watch dog timer to 8 secs
- readlinks(); // set timings
- if(datalogging || testing) init_soft_spi(); // change function of pins used SPI and dil sws
- else disable_spipins(); // all to inputs with no pull ups
- POWER_LATCH = POWER_ON;
- MOTOR_DRIVE = MOTOR_OFF;
- timeout = shutdown_time;
- switchstate = SW_CLOSED; // it must be since power has been applied
- fault |= INITIAL_BLEEP;
- while(seconds != 2) ; // wait, short bleep on alarm
- fault &= ~INITIAL_BLEEP;
- batvolts = getbatvolts();
- if(datalogging)
- {
- txheader();
- printf("Battery voltage = %d\r\n",batvolts);
- }
- cycletime = 2; // ensure motor runs to next cam position at power on
- while(1)
- {
- #asm
- WDR
- #endasm
- if(localsecs != seconds)
- {
- localsecs = seconds;
- if((seconds & 0x0F) == 0x0F) batvolts = getbatvolts();
- }
- if(batvolts > SWITCH_LIM) // there is flow/pressure so reset timeout
- {
- switchstate = SW_CLOSED;
- timeout = shutdown_time;
- }
- else
- {
- switchstate = !SW_CLOSED;
- }
- if(batvolts > SWITCH_LIM && batvolts < BAT_LIM) fault |= BATTERY_FAULT;
- else fault &= ~BATTERY_FAULT;
- if(datalogging && timetoprint != print_timer)
- {
- timetoprint = print_timer;
- printf("%d %d %d %d",cycletime,batvolts, ~switchstate,CAM_SW);
- printf (" %-4d %d %d \r\n",timeout,MOTOR_PIN,motor_timer);
- }
- if(!cycletime) // time to start motor again,
- {
- cycletime = cycletime_reload;
- motor_timer = MOTOR_TIMEOUT;
- MOTOR_DRIVE = MOTOR_ON;
- while(CAM_SW == CAM_INTROUGH && motor_timer ) ; // let switch get out of trough
- while(tenthsecs < 3) ; // and run for 0.3 seconds
- }
- if(!motor_timer && MOTOR_PIN) // motor timed out, motor power still on so motor stalled
- {
- fault |= MOTOR_FAULT;
- }
- if(CAM_SW == CAM_INTROUGH || fault & MOTOR_FAULT && MOTOR_PIN) // time to stop motor
- {
- MOTOR_DRIVE = MOTOR_OFF;
- if(timeout == 0)
- {
- if(datalogging) printf("\r\nShutting down\r\n");
- delay_us(1000); // time to send data out
- POWER_LATCH = POWER_OFF; // turn processor off
- #asm
- WDR
- #endasm
- while(1) ; // use up residual charge on Vcc capacitors
- }
- }
- }
- }
- //*****************************************************************
- void readlinks(void) // determine cycle time that is wanted
- // and whether or not plugged into test rig
- // MISO line PA.5 normally high , low if in testing
- // SS line PA.3 low to turn data logging on
- {
- char speedselect;
- links = (PINA>>3) & 0b00001111;
- if(links & 0x01) datalogging = FALSE; // SS line high so not connected to logging board
- else datalogging = TRUE;
- if(links & 0x04) testing =FALSE; // MISO line is high
- else testing = TRUE;
- speedselect = links>>1 & 0b00000111;
- cycletime_reload = speedtable[speedselect][0];
- shutdown_time = speedtable[speedselect][1];
- }
- //*************************************************************
- int getbatvolts(void) // return measured voltage in units of 1/100 volts
- // measure reference on chan 0 to calibrate then use direct ratio
- // to determine battery voltage
- {
- unsigned long int reading;
- int i;
- long batvolts;
- long extrefvolts;
- PRR &= ~ 1<<PRADC; // power up ADC
- ADMUX =0;
- ADCSRA = 1<<ADEN | 1<<ADSC | 0<<ADATE | 1<<ADIF | 0<<ADIE | 0x01; // freq div 2
- while(ADCSRA & 1<<ADSC) ; // wait for conversion to complete
- ADCSRA &= 0; //stop A-D to save power
- reading = ADCL;
- i = ADCH;
- i <<= 8;
- reading += i;
- extrefvolts = reading;
- ADMUX |= BATCHAN;
- ADCSRA = 1<<ADEN | 1<<ADSC | 0<<ADATE | 1<<ADIF | 0<<ADIE | 0x01; // freq div 2
- while(ADCSRA & 1<<ADSC) ; // wait for conversion to complete
- ADCSRA &= 0; //stop A-D to save power
- PRR |= 1<< PRADC;
- reading = ADCL;
- i = ADCH;
- i <<= 8;
- reading += i;
- batvolts = reading;
- // printf("\r\n ref = %d bat = %d\r\n",extrefvolts,batvolts);
- reading = VREF * batvolts;
- reading *= (R1+R2);
- reading /= R2;
- reading /= extrefvolts;
- return((int)reading);
- }
- //************************************************************
- void alarm(char control) // control takes either ALARM_ON or ALARM_OFF
- // timer 0 used in CTC mode to give around 4KHz to piezo alarm
- // called from interrupt routine
- {
- if(((TCCR0A & 0b01000010) != 0b01000010) && control == ALARM_ON) // alarm was not on but now wanted on
- {
- TCCR0A = 0b01000010; // toggle OC0A on match
- TCCR0B = 0b00000001; // no prescale
- OCR0A = 18; // to give close to 3.5Hz ouput freq.
- }
- else
- {
- if(TCCR0A != 0x00 && control != ALARM_ON) // alarm was not off but now wanted off
- {
- TCCR0A = 0x00; // timer 0 off
- TCCR0B = 0x00;
- }
- }
- }
- //**************************************************************
- void putchar(char c) // send character to SPI using software
- {
- char i;
- SPI_CLK = 0;
- SS_LINE = 0;
- for(i=0;i<8;i++)
- {
- PORTA.6 = c & 0x80;
- SPI_CLK = 1;
- c <<= 1;
- SPI_CLK = 0;
- }
- SS_LINE = 1;
- }
- //************************************************************
- void txheader(void)
- {
- printf("%p compiled %p @ %p\r\n",__FILE__,__DATE__,__TIME__);
- printf("Links = %d\r\n",links);
- printf("Cycle time = %d seconds\r\n",cycletime_reload);
- printf("Shutdown time = %d seconds\r\n\r\n",shutdown_time);
- if(testing)
- {
- printf("Test mode\r\n");
- }
- }
- //***************************************************
- void init_soft_spi(void) // change port pins used for links and SPI to outputs
- {
- DDRA |= 0b01011000; // PA6 MOSI, PA4 UCLK , PA3 SS, as outputs
- SS_LINE = 1;
- SPI_CLK = 0;
- }
- //********************************************************
- void disable_spipins() // dil switch inputs to become outputs and lowall to inputs with no pull ups to save power
- // Serial unused lines to inputs with pull ups
- {
- PORTA = 0b00101100; // PA5,PA3 these are inputs so now pull ups are on
- DDRA = 0b11010000;
- }
- //*****************************************************
- void resurrectdog(void) // reset dog timer to 8 secs
- // written in assembler to prevent optimiser changing
- // code
- {
- #asm
- CLI //stop interrupts
- WDR // reset watchdog
- IN R30,MCUSR
- CBR R30,3 ; WDRF bit
- OUT MCUSR,R30 ; clear WDRF
- LDI R31,0b00110001 ; WDCE set WDE cleared
- LDI R30,0b00101001; WDE set WDCE cleared 8 secs
- OUT WDTCSR,R31 ; WDE and WDCE bits set
- OUT WDTCSR,R30
- SEI
- #endasm
- }
- //***************************************************
- void inithw(void)
- {
- // timer 0 ctc mode to alarm OC0A pin drives alarm
- TCCR0A = 0x00; // CTC, toggle on match will be set in alarm() function
- TCCR0B = 0x00; //
- // timer 1 used for timing phase correct 8 bit halves inerrupt rate
- TCCR1A = 0<<WGM11 | 1<<WGM10;
- TCCR1B = 0<<WGM13 | 0<<WGM12 | 1<<CS10;
- TIMSK1 = 1<<TOIE1;
- // ADC initialized in getbatvolts()
- PORTA = 0b01111100;
- DDRA = 0b10000000; // B7(power latch) B6 (MOSI , link) , B2 (cam),B1 bat volts,B0 adc ref
- // leave B3 (SS_LINE), B4 (SPI_CLK,link ) B5 (MISO,link) as inputs
- // change after DIL sws and links read to allow for software SPI output
- DIDR0 = 0b00000011; // digital disable for A0 and A1
- PORTB = 0b00000101; // LED off motor off alarm drive high
- DDRB = 0b00000111; // PB0,PB1,PB2 LED drive,motor drive, Alarm drive
- PRR |= 1<<PRUSI; // power off to USI system
- ACSR |= 1<<ACD; // power of analogue comparator
- #asm
- SEI
- #endasm
- }
- //*******************************************************
Add Comment
Please, Sign In to add comment