Guest User

Untitled

a guest
Apr 20th, 2018
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.69 KB | None | 0 0
  1. /*
  2.  
  3. FILE .......................... S_DRYER_2.C
  4.  
  5. DATE ....................... 21-3-18
  6.  
  7. CONTENT
  8. All code for simple dryer started November 2107
  9. S_DRYER_2.C for 1st off pcb
  10.  
  11.  
  12.  
  13. Processor TINY44A
  14.  
  15. FUSES E4 DE FF
  16.  
  17. No clock division
  18. No clock output
  19. SUT1 1
  20. SUT0 0
  21. CLOCK 128Khz
  22. Brown Out 1.8 Volts
  23.  
  24.  
  25.  
  26. HARDWARE USAGE
  27.  
  28. TIMER 1 (8 bit) ....................... Timing
  29. TIMER 0 ............................ Generate alarm drive frequency
  30.  
  31.  
  32. DIP pinning
  33. PIn 1 ..... Vcc
  34. Pin 2 ..... PB0 .................................. Green LED
  35. Pin 3 ..... PB1 ................................... Motor drive
  36. Pin 4 ..... PB3 /RESET ....................... Programming
  37. Pin 5 ..... PB2 / OC0A ....................... Audio Alarm drive
  38. Pin 6 ..... PA7 ................................... Power latch
  39. PIn 7 ..... PA6 / MOSI ...................... DIL SW , Programming.
  40. Pin 8 ..... PA5 / MISO ....................... Programming, 'test mode' rig detection
  41. Pin 9 ..... PA4 / UCLK ........................ DIL SW , Programming and data output
  42. Pin 10 ..... PA3 ..................................... Used as SS for SPI output , ' logging' detection
  43. Pin 11 ..... PA2 / ADC2 ......................... Cam sensor
  44. Pin 12 ..... PA1 /ADC1 .......................... Battery voltage
  45. Pin 13 ...... PA0 / AREF ....................... reference diode for A-D use
  46. Pin 14 ...... GRND
  47.  
  48. */
  49.  
  50.  
  51. #include "TINY44.H" // bits included in this header
  52.  
  53. #include "STDLIB.H"
  54. #include "STDIO.H"
  55. #include "DELAY.H"
  56. #include "MATH.H"
  57.  
  58. #define FALSE 0
  59. #define TRUE !FALSE
  60.  
  61. #define _ALTERNATE_PUTCHAR_ // lib function replaced, op goes to SPI
  62.  
  63. #define OSC 128000 // low freq internal osc
  64. #define PRESCALE 1 // for timer 0
  65. #define PRESCALE_BITS 0x01 // no prescale ie 1 0x02 // to give prescale of 8
  66. #define DEF_MOTOR_TIME 30 // 1/10 seconds for cam to get beyond switch
  67. #define SHUTDOWNTIME 420 // seconds after flow/pressure switch opens before power removed
  68. #define MOTOR_TIMEOUT 5 // seconds max time motor on for
  69. #define BAT_LIM 250 // 1/100 volts battery at end of life
  70. #define SWITCH_LIM 100 // 1/100 volts below this means swich open
  71. #define R1 100 // K ohms potential divider for battery volts
  72. #define R2 47 // K ohms potentaial divider for battery volts
  73.  
  74. #define ADCFSD 1024
  75. #define VREF 122 // units 1/100 volts
  76. #define BATCHAN 0x01 // ADC1 used for measuring battery voltage
  77.  
  78. #define POWER_LATCH PORTA.7
  79. #define POWER_ON 1
  80. #define POWER_OFF 0
  81. #define GREEN_LED PORTB.0
  82. #define LED_ON 0
  83. #define LED_OFF 1
  84. #define ALARM_ON 0
  85. #define ALARM_OFF !ALARM_ON
  86.  
  87. #define MOTOR_DRIVE PORTB.1
  88. #define MOTOR_PIN PINB.1
  89. #define MOTOR_ON 1
  90. #define MOTOR_OFF 0
  91. #define CAM_SW PINA.2
  92. #define CAM_INTROUGH 1 // cam switch open ie. in the trough in the cam
  93. #define SW_CLOSED 0
  94. #define SW_OPEN !SW_CLOSED
  95. #define SS_LINE PORTA.3
  96. #define SPI_CLK PORTA.4
  97. #define SPI_DO PORTA.6
  98.  
  99. #define MOTOR_FAULT 0x01
  100. #define BATTERY_FAULT 0x02
  101. #define INITIAL_BLEEP 0x80 // artificial 'fault' to cause alarm to sound at power up
  102.  
  103. // Functions
  104.  
  105. void readlinks(void); // for setting switching speed between dryer canisters returns seconds
  106. int getbatvolts(void); // returns in units of 1/100 volts
  107. void inithw(void); // set internal registers
  108. void txheader(void); // send useful ident stuff to terminal
  109. void init_soft_spi(void); // change port pins used for links and SPI to outputs
  110. void resurrectdog(void); // reset watchdog timer to 8 secs
  111. void alarm(char control); // control takes either ALARM_ON or ALARM_OFF
  112. void disable_spipins(); // all to inputs with no pull ups
  113.  
  114.  
  115. // Global variables
  116. int speedtable[8][2] = // seconds selected by links cycle_reload , shutdown time links decimal
  117. {
  118. {5,10}, // both dil sws on in test mode 000 0
  119. {10,20}, // sw1 off sw2 on in test mode 001 2
  120. {1800,3600}, // both dil sws on normal mode 010 4
  121. {3600,7200}, // dil sw 1 off dil sw 2 on normal 011 6
  122. {15,30}, // dil sw 1 off dilsw 2 off test 100 8
  123. {20,40}, // dilsw 1 off dil sw 2 off test 101 10
  124. {7200, 14400}, // dil sw 1 on ,dilsw 2 off normal 110 12
  125. {14400,14400}, // dil sw 1 off ,dilsw 2 off normal 111 14
  126. };
  127.  
  128. char tenthsecs; // increments 0-9
  129. char seconds; // increments on close to 1 second interval
  130. char motor_timer; // for detecting stalled motor
  131. int cycletime_reload; // seconds set by which links fitted
  132. int cycletime; // timer that is actually used
  133. int shutdown_time; // seconds after flow stops before sytem powers down set by links
  134. int timeout; // timing for removing power after no flow/pressure
  135.  
  136. char print_timer;
  137. char links; // only used for printing state of links
  138. char fault; // bit mapped for different faults
  139. bit switchstate; // monitors flow/pressure switch by measuring voltage
  140. bit datalogging; // controlled by inverse of state of SS line at power on, when set data sent out to SPI
  141. bit testing; // controlled by inverse of state of MISO line at power on, when set use test values for cycle time
  142.  
  143. //**************************************************************************************
  144. interrupt[TIM1_OVF] void timer0(void) // 1Mhz clock prescale 8 overflow rate 488 per sec
  145. //128 KHz prescale 1 overflow rate 250 per sec because
  146. // in 8 bit phase correct mode
  147. // execution time approx 150 to 250 microsec at 128KHz OSC
  148. {
  149. static int count =OSC/256/PRESCALE/10/2;
  150.  
  151.  
  152. if(--count == 0)
  153. {
  154. count = OSC/256/PRESCALE/10/2;
  155. if(++tenthsecs == 10)
  156. {
  157. GREEN_LED = LED_ON;
  158. tenthsecs = 0;
  159. ++seconds;
  160. print_timer++;
  161. if(cycletime) cycletime--;
  162. if(motor_timer) motor_timer--;
  163. if( switchstate == SW_OPEN && timeout) timeout--;
  164. if(seconds < 13 && fault & seconds || fault & INITIAL_BLEEP) alarm(ALARM_ON);
  165. else alarm(ALARM_OFF);
  166. GREEN_LED = LED_OFF;
  167. }
  168. }
  169.  
  170. }
  171.  
  172. //*************************************************
  173. void main(void)
  174.  
  175. {
  176. char localsecs =5;
  177. int batvolts; // units 1/100 volts measured voltage
  178. char timetoprint = 10; // keep compiler happy
  179.  
  180. inithw();
  181. resurrectdog(); // set watch dog timer to 8 secs
  182.  
  183.  
  184. readlinks(); // set timings
  185. if(datalogging || testing) init_soft_spi(); // change function of pins used SPI and dil sws
  186. else disable_spipins(); // all to inputs with no pull ups
  187.  
  188. POWER_LATCH = POWER_ON;
  189. MOTOR_DRIVE = MOTOR_OFF;
  190.  
  191. timeout = shutdown_time;
  192. switchstate = SW_CLOSED; // it must be since power has been applied
  193.  
  194.  
  195. fault |= INITIAL_BLEEP;
  196. while(seconds != 2) ; // wait, short bleep on alarm
  197. fault &= ~INITIAL_BLEEP;
  198.  
  199. batvolts = getbatvolts();
  200.  
  201. if(datalogging)
  202. {
  203. txheader();
  204. printf("Battery voltage = %d\r\n",batvolts);
  205. }
  206. cycletime = 2; // ensure motor runs to next cam position at power on
  207.  
  208. while(1)
  209. {
  210. #asm
  211. WDR
  212. #endasm
  213.  
  214. if(localsecs != seconds)
  215. {
  216. localsecs = seconds;
  217. if((seconds & 0x0F) == 0x0F) batvolts = getbatvolts();
  218. }
  219.  
  220.  
  221. if(batvolts > SWITCH_LIM) // there is flow/pressure so reset timeout
  222. {
  223. switchstate = SW_CLOSED;
  224. timeout = shutdown_time;
  225. }
  226. else
  227. {
  228. switchstate = !SW_CLOSED;
  229. }
  230.  
  231. if(batvolts > SWITCH_LIM && batvolts < BAT_LIM) fault |= BATTERY_FAULT;
  232. else fault &= ~BATTERY_FAULT;
  233.  
  234.  
  235.  
  236.  
  237. if(datalogging && timetoprint != print_timer)
  238. {
  239. timetoprint = print_timer;
  240. printf("%d %d %d %d",cycletime,batvolts, ~switchstate,CAM_SW);
  241. printf (" %-4d %d %d \r\n",timeout,MOTOR_PIN,motor_timer);
  242. }
  243.  
  244. if(!cycletime) // time to start motor again,
  245. {
  246. cycletime = cycletime_reload;
  247. motor_timer = MOTOR_TIMEOUT;
  248. MOTOR_DRIVE = MOTOR_ON;
  249. while(CAM_SW == CAM_INTROUGH && motor_timer ) ; // let switch get out of trough
  250. while(tenthsecs < 3) ; // and run for 0.3 seconds
  251. }
  252.  
  253.  
  254. if(!motor_timer && MOTOR_PIN) // motor timed out, motor power still on so motor stalled
  255. {
  256. fault |= MOTOR_FAULT;
  257. }
  258.  
  259.  
  260. if(CAM_SW == CAM_INTROUGH || fault & MOTOR_FAULT && MOTOR_PIN) // time to stop motor
  261. {
  262. MOTOR_DRIVE = MOTOR_OFF;
  263. if(timeout == 0)
  264. {
  265. if(datalogging) printf("\r\nShutting down\r\n");
  266. delay_us(1000); // time to send data out
  267. POWER_LATCH = POWER_OFF; // turn processor off
  268. #asm
  269. WDR
  270. #endasm
  271. while(1) ; // use up residual charge on Vcc capacitors
  272. }
  273. }
  274.  
  275.  
  276. }
  277.  
  278.  
  279. }
  280.  
  281.  
  282. //*****************************************************************
  283. void readlinks(void) // determine cycle time that is wanted
  284. // and whether or not plugged into test rig
  285. // MISO line PA.5 normally high , low if in testing
  286. // SS line PA.3 low to turn data logging on
  287. {
  288. char speedselect;
  289.  
  290. links = (PINA>>3) & 0b00001111;
  291. if(links & 0x01) datalogging = FALSE; // SS line high so not connected to logging board
  292. else datalogging = TRUE;
  293.  
  294. if(links & 0x04) testing =FALSE; // MISO line is high
  295. else testing = TRUE;
  296.  
  297. speedselect = links>>1 & 0b00000111;
  298.  
  299. cycletime_reload = speedtable[speedselect][0];
  300. shutdown_time = speedtable[speedselect][1];
  301.  
  302. }
  303. //*************************************************************
  304. int getbatvolts(void) // return measured voltage in units of 1/100 volts
  305. // measure reference on chan 0 to calibrate then use direct ratio
  306. // to determine battery voltage
  307.  
  308. {
  309. unsigned long int reading;
  310. int i;
  311. long batvolts;
  312. long extrefvolts;
  313.  
  314. PRR &= ~ 1<<PRADC; // power up ADC
  315.  
  316. ADMUX =0;
  317. ADCSRA = 1<<ADEN | 1<<ADSC | 0<<ADATE | 1<<ADIF | 0<<ADIE | 0x01; // freq div 2
  318.  
  319. while(ADCSRA & 1<<ADSC) ; // wait for conversion to complete
  320. ADCSRA &= 0; //stop A-D to save power
  321.  
  322. reading = ADCL;
  323. i = ADCH;
  324. i <<= 8;
  325. reading += i;
  326. extrefvolts = reading;
  327.  
  328. ADMUX |= BATCHAN;
  329. ADCSRA = 1<<ADEN | 1<<ADSC | 0<<ADATE | 1<<ADIF | 0<<ADIE | 0x01; // freq div 2
  330.  
  331. while(ADCSRA & 1<<ADSC) ; // wait for conversion to complete
  332. ADCSRA &= 0; //stop A-D to save power
  333. PRR |= 1<< PRADC;
  334.  
  335. reading = ADCL;
  336.  
  337. i = ADCH;
  338. i <<= 8;
  339. reading += i;
  340. batvolts = reading;
  341. // printf("\r\n ref = %d bat = %d\r\n",extrefvolts,batvolts);
  342. reading = VREF * batvolts;
  343. reading *= (R1+R2);
  344. reading /= R2;
  345. reading /= extrefvolts;
  346.  
  347. return((int)reading);
  348.  
  349. }
  350. //************************************************************
  351. void alarm(char control) // control takes either ALARM_ON or ALARM_OFF
  352. // timer 0 used in CTC mode to give around 4KHz to piezo alarm
  353. // called from interrupt routine
  354. {
  355.  
  356.  
  357. if(((TCCR0A & 0b01000010) != 0b01000010) && control == ALARM_ON) // alarm was not on but now wanted on
  358. {
  359. TCCR0A = 0b01000010; // toggle OC0A on match
  360. TCCR0B = 0b00000001; // no prescale
  361. OCR0A = 18; // to give close to 3.5Hz ouput freq.
  362. }
  363.  
  364. else
  365. {
  366. if(TCCR0A != 0x00 && control != ALARM_ON) // alarm was not off but now wanted off
  367. {
  368. TCCR0A = 0x00; // timer 0 off
  369. TCCR0B = 0x00;
  370. }
  371. }
  372.  
  373.  
  374. }
  375.  
  376. //**************************************************************
  377. void putchar(char c) // send character to SPI using software
  378. {
  379. char i;
  380.  
  381. SPI_CLK = 0;
  382. SS_LINE = 0;
  383.  
  384. for(i=0;i<8;i++)
  385. {
  386. PORTA.6 = c & 0x80;
  387. SPI_CLK = 1;
  388. c <<= 1;
  389. SPI_CLK = 0;
  390. }
  391.  
  392. SS_LINE = 1;
  393. }
  394. //************************************************************
  395.  
  396. void txheader(void)
  397. {
  398.  
  399. printf("%p compiled %p @ %p\r\n",__FILE__,__DATE__,__TIME__);
  400. printf("Links = %d\r\n",links);
  401. printf("Cycle time = %d seconds\r\n",cycletime_reload);
  402. printf("Shutdown time = %d seconds\r\n\r\n",shutdown_time);
  403. if(testing)
  404. {
  405. printf("Test mode\r\n");
  406. }
  407. }
  408. //***************************************************
  409. void init_soft_spi(void) // change port pins used for links and SPI to outputs
  410.  
  411. {
  412. DDRA |= 0b01011000; // PA6 MOSI, PA4 UCLK , PA3 SS, as outputs
  413. SS_LINE = 1;
  414. SPI_CLK = 0;
  415.  
  416. }
  417. //********************************************************
  418. void disable_spipins() // dil switch inputs to become outputs and lowall to inputs with no pull ups to save power
  419. // Serial unused lines to inputs with pull ups
  420. {
  421. PORTA = 0b00101100; // PA5,PA3 these are inputs so now pull ups are on
  422. DDRA = 0b11010000;
  423. }
  424. //*****************************************************
  425.  
  426. void resurrectdog(void) // reset dog timer to 8 secs
  427. // written in assembler to prevent optimiser changing
  428. // code
  429. {
  430. #asm
  431. CLI //stop interrupts
  432. WDR // reset watchdog
  433. IN R30,MCUSR
  434. CBR R30,3 ; WDRF bit
  435. OUT MCUSR,R30 ; clear WDRF
  436.  
  437. LDI R31,0b00110001 ; WDCE set WDE cleared
  438. LDI R30,0b00101001; WDE set WDCE cleared 8 secs
  439.  
  440. OUT WDTCSR,R31 ; WDE and WDCE bits set
  441. OUT WDTCSR,R30
  442. SEI
  443.  
  444. #endasm
  445.  
  446. }
  447.  
  448. //***************************************************
  449.  
  450. void inithw(void)
  451. {
  452.  
  453. // timer 0 ctc mode to alarm OC0A pin drives alarm
  454. TCCR0A = 0x00; // CTC, toggle on match will be set in alarm() function
  455. TCCR0B = 0x00; //
  456.  
  457.  
  458. // timer 1 used for timing phase correct 8 bit halves inerrupt rate
  459.  
  460. TCCR1A = 0<<WGM11 | 1<<WGM10;
  461. TCCR1B = 0<<WGM13 | 0<<WGM12 | 1<<CS10;
  462.  
  463. TIMSK1 = 1<<TOIE1;
  464.  
  465. // ADC initialized in getbatvolts()
  466.  
  467.  
  468. PORTA = 0b01111100;
  469. DDRA = 0b10000000; // B7(power latch) B6 (MOSI , link) , B2 (cam),B1 bat volts,B0 adc ref
  470. // leave B3 (SS_LINE), B4 (SPI_CLK,link ) B5 (MISO,link) as inputs
  471. // change after DIL sws and links read to allow for software SPI output
  472.  
  473. DIDR0 = 0b00000011; // digital disable for A0 and A1
  474.  
  475. PORTB = 0b00000101; // LED off motor off alarm drive high
  476. DDRB = 0b00000111; // PB0,PB1,PB2 LED drive,motor drive, Alarm drive
  477.  
  478. PRR |= 1<<PRUSI; // power off to USI system
  479. ACSR |= 1<<ACD; // power of analogue comparator
  480.  
  481. #asm
  482. SEI
  483. #endasm
  484. }
  485.  
  486. //*******************************************************
Add Comment
Please, Sign In to add comment