示例#1
0
int main(void)
{
    // Make the watchdog timer cause an interrupt rather than system reset and
    // use C/256K prescaler.
    MCUSR &= ~_BV(WDRF);
    wdt_disable();
    WDTCR |= _BV(WDTIF) | _BV(WDP2) | _BV(WDP1) | _BV(WDP0);

    // Configure all pins as outputs except the temperature input pin and the
    // TX pin (which is tri-stated until we transmit).
    DDRB = 0xFF ^ _BV(TEMP_SENSE_INPUT_DIG_PIN) ^ _BV(TX_PIN);
    // Disable digital input buffer on the analog input pin.
    DIDR0 |= _BV(TEMP_SENSE_INPUT_DIG_PIN);

    // Enable interrupts.
    sei();

    while (1)
    {
        manchester_union.manchester_packet.node_id = NODE_ID;
        manchester_union.manchester_packet.seq_no += 1;
        manchester_union.manchester_packet.reading_type = READING_TYPE_TEMP;
        manchester_union.manchester_packet.reading = read_temperature();
        transmit();
        deep_sleep();
    }

    return (1); // should never happen
}
示例#2
0
void epd_enable(void)
{
	char temp = TEMP_USE_DEFAULT;
	debug("epd_enable\n");
	
	//epdc_power_on();
	/* Draw data to display */
	//draw_mode0();

	/* Enable clock gating (clear to enable) */
	REG_CLR(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_CLKGATE);
	while (REG_RD(EPDC_BASE, EPDC_CTRL) &
	       (EPDC_CTRL_SFTRST | EPDC_CTRL_CLKGATE))
		;

	REG_WR(EPDC_BASE, EPDC_TEMP, TEMP_USE_DEFAULT);
	temp = read_temperature();
//	temp = do_read_temperature_via_i2c();
	temp_set_index(temp);
	
	/* Set Waveform Bufferr register to real waveform address */
	REG_WR(EPDC_BASE, EPDC_WVADDR, panel_info.epdc_data.waveform_buf_addr);

	debug("epdc_irq's value %08x\nEPDC_IRQ_CLR's value %08x\n",REG_RD(EPDC_BASE, EPDC_IRQ), REG_RD(EPDC_BASE, EPDC_IRQ_CLR));
	debug("EPDC LUT STATUS %08x\n",REG_RD(EPDC_BASE,EPDC_STATUS_LUTS));
	draw_splash_screen();
	debug("epdc_irq's value %08x\nEPDC_IRQ_CLR's value %08x\n",REG_RD(EPDC_BASE, EPDC_IRQ), REG_RD(EPDC_BASE, EPDC_IRQ_CLR));
	debug("EPDC LUT STATUS %08x\n",REG_RD(EPDC_BASE,EPDC_STATUS_LUTS));
}
bool GroveTempHumPro::read_temperature_f(float *temperature)
{
    float t;
    if (!read_temperature(&t)) return false;
    *temperature = _convertCtoF(t);
    return true;
}
void main()
{
   init_pic();

     initialDisplay();
     t = read_adc();

   OUTPUT_HIGH(PIN_C0);
   OUTPUT_HIGH(PIN_C2);
   OUTPUT_LOW(PIN_C3);
       while(1)
       {
       //  if(number_changed)
      //   {
            lcd_display(noOfPeople,14,1);
      //      number_changed = 0;
      //   }
         read_temperature();
         if(temp_changed)
         {
            lcd_display(temperature,13,2);
            temp_changed = 0;
         }

       //  phaseControl();

       }
}
int main() {
	printf("Begin\n");

/* @param	system_init			initialize GPIO and ADC structs for pins and ADC variables using system_init()
*  @param	SysTick_Config		set ticks by dividing systemCoreClock with systick frequency (168MHz/50Hz)
*  @param	read_temperature() 	used to convert digital signal to temperature reading
*  @param	filtered			defined as moving average to reduce noise
*  @param	motor_rotate_to  	for the servo motor measurements (with filtered angle measurements)
*  @param	alarm_temperature 	defined to raise the alarm if the temperature goes above threshold
*/	
	system_init();

	SysTick_Config(SystemCoreClock / SYSTICK_FREQUENCY);
	//running while loop to control the frequency measurement readings of the temperature 
	//waits for interrupt to read the temperature readings
	while (1) {
		while (!system_ticks);
		
		read_temperature();

		float filtered = ma_filter(temperature_reading);
		motor_rotate_to(temperature_to_angle(filtered));
		alarm_temperature(filtered);

		system_ticks = 0;

		
	}
	
	
	return 0;
}
示例#6
0
int main()
{
	while(1) 
	{
		double temperature = read_temperature(); 
		_delay_ms(500);
		double pressure = read_presure(); 
		_delay_ms(500);
	}
}
/*
 * Instruct the DHT to begin sampling.  Keep polling until it returns true.
 * The tempearture is in degrees Celsius, and the humidity is in %.
 */
bool DHT_nonblocking::measure( float *temperature, float *humidity )
{
  if( read_nonblocking( ) == true )
  {
    *temperature = read_temperature( );
    *humidity    = read_humidity( );
    return( true );
  }
  else
  {
    return( false );
  }
}
示例#8
0
static inline void
read_child_node (GWeatherInfo *info,
		 xmlNodePtr    node)
{
    if (strcmp ((char*) node->name, "symbol") == 0)
	read_symbol (info, node);
    else if (strcmp ((char*) node->name, "windDirection") == 0)
	read_wind_direction (info, node);
    else if (strcmp ((char*) node->name, "windSpeed") == 0)
	read_wind_speed (info, node);
    else if (strcmp ((char*) node->name, "temperature") == 0)
	read_temperature (info, node);
    else if (strcmp ((char*) node->name, "pressure") == 0)
	read_pressure (info, node);
    else if (strcmp ((char*) node->name, "humidity") == 0)
        read_humidity (info, node);
}
示例#9
0
static void 
timeout_handler(void)
{
#if DEV_BOARD
	leds_toggle(LEDS_GREEN);
#endif	


#if HAS_TEMP_SENSOR
	my_temp = get_temperature();
	read_temperature();
#endif

#if HAS_LIGHT_SENSOR
	my_light = get_brightness();
	light_sensor_start_conversion();
#endif

}
void temperature_timer_interrupt (void)
{

	char buf[16];
	u08 i;
	short temperature;

	if(conf->current_sector > mmcSectorCount) {
		cbi(PORTA,PA0);
		return;
	}
	else {
		sbi(PORTA,PA0);
	}

  
	do {
		temperature = read_temperature();
	} while(temperature>>TEMPERATURE_POINT < -200);

	// Format temperature.
	format_temperature(buf, temperature);
	for (i = 0; buf[i] != '.'; i++);
	if (buf[i + 2] >= '5')
		buf[i + 1]++;
	buf[i + 2] = '\0';

	//cbi(PORTA, PA0);
	if (mmc_buf_i != 0 || conf->current_sector != START_SECTOR)
		write_char('\n');

	for (i = 0; buf[i] != '\0'; i++)
		write_char(buf[i]);

	write_char('\0');
	mmc_buf_i--;

	// Write to sector.
	mmcWrite(conf->current_sector, mmc_buf);

	//sbi(PORTA, PA0);
}
示例#11
0
文件: aad.c 项目: elberskirch/aad
static void worker(int fd, short event, void *arg) {
    struct timeval tv;
    struct event *timeout = arg;
    int newtime = time(NULL);
    unsigned char buf = 0;
    char wbuf[80];
    unsigned char len = 0;
    off_t r;
    time_t now;
    char timebuf[40];
     
    buf = read_temperature();    
    now = time(NULL);
    strftime(timebuf, 40, "%c", localtime(&now));
    switch(fan_state) {
        case FAN_OFF:
           if( buf >= START_TEMP )
              start_fan();
           break;
        case FAN_ON:
           if( buf <= STOP_TEMP )
              stop_fan();
           break;
    }      
    
    if( logger ) {
        len = sprintf(wbuf, "[%s] fan_state: %d temp: %d deg c\n", 
                      timebuf, fan_state, buf); 
        if( !demon ) 
            write(1, wbuf, len);
        write(logfile, wbuf, len);
    }

    lasttime = newtime;
        
    evutil_timerclear(&tv);
    tv.tv_sec = interval.tv_sec;
    event_add(timeout, &tv);
}
示例#12
0
/// called every 10ms from clock.c - check all temp sensors that are ready for checking
void temp_sensor_tick() {
	temp_sensor_t i = 0;
	for (; i < NUM_TEMP_SENSORS; i++) {
		if (temp_sensors_runtime[i].next_read_time) {
			temp_sensors_runtime[i].next_read_time--;
		}
		else {
			uint16_t	temp = 0;
			//time to deal with this temp sensor
			switch(temp_sensors[i].temp_type) {
				#ifdef	TEMP_MAX6675
				case TT_MAX6675:
					#ifdef	PRR
						PRR &= ~MASK(PRSPI);
					#elif defined PRR0
						PRR0 &= ~MASK(PRSPI);
					#endif
                    #ifdef NAL_REPRAP
                        /* This section is compatible with the mendel original implementation of the MAX6675.
                         * Not using the SPI as the MISO line is used to control our heater.
                         */

                        WRITE(MAX6675_CS, 0); // Enable device

                        // Read in 16 bits from the MAX6675 
                        for (uint8_t i=0; i<16; i++){
                            WRITE(MAX6675_SCK,1);                               // Set Clock to HIGH
                            temp <<= 1;                                         // shift left by one
                            // Read bit  and add it to our variable
                            temp +=  (READ(MAX6675_SO) != 0 );
                            WRITE(MAX6675_SCK,0);                               // Set Clock to LOW
                        }

                        WRITE(MAX6675_CS, 1);                                   //Disable Device
                    #else
                        SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);

                        // enable TT_MAX6675
                        WRITE(SS, 0);

                        // ensure 100ns delay - a bit extra is fine
                        delay(1);

                        // read MSB
                        SPDR = 0;
                        for (;(SPSR & MASK(SPIF)) == 0;);
                        temp = SPDR;
                        temp <<= 8;

                        // read LSB
                        SPDR = 0;
                        for (;(SPSR & MASK(SPIF)) == 0;);
                        temp |= SPDR;

                        // disable TT_MAX6675
                        WRITE(SS, 1);
                    #endif
					temp_sensors_runtime[i].temp_flags = 0;
					if ((temp & 0x8002) == 0) {
						// got "device id"
						temp_sensors_runtime[i].temp_flags |= PRESENT;
						if (temp & 4) {
							// thermocouple open
							temp_sensors_runtime[i].temp_flags |= TCOPEN;
						}
						else {
							temp = temp >> 3;
						}
					}

					// this number depends on how frequently temp_sensor_tick is called. the MAX6675 can give a reading every 0.22s, so set this to about 250ms
					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_MAX6675	*/

				#ifdef	TEMP_THERMISTOR
				case TT_THERMISTOR:
					do {
						uint8_t j, table_num;
						//Read current temperature
						temp = analog_read(temp_sensors[i].temp_pin);
                        
                        // check for open circuit
                        if (temp ==1023){
                           temp = 0 ; // this should convert to max temperature and ensure the heaters are turned off
                           temp_sensors_runtime[i].temp_flags |= TCOPEN;
                        }
                        
						// for thermistors the thermistor table number is in the additional field
						table_num = temp_sensors[i].additional;
                        

						//Calculate real temperature based on lookup table
						for (j = 1; j < NUMTEMPS; j++) {
							if (pgm_read_word(&(temptable[table_num][j][0])) > temp) {
								// Thermistor table is already in 14.2 fixed point
								#ifndef	EXTRUDER
								if (debug_flags & DEBUG_PID)
									sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),temp_sensors[i].temp_pin,temp,j);
								#endif
								// Linear interpolating temperature value
								// y = ((x - x₀)y₁ + (x₁-x)y₀ ) / (x₁ - x₀)
								// y = temp
								// x = ADC reading
								// x₀= temptable[j-1][0]
								// x₁= temptable[j][0]
								// y₀= temptable[j-1][1]
								// y₁= temptable[j][1]
								// y =
								// Wikipedia's example linear interpolation formula.
								temp = (
								//     ((x - x₀)y₁
									((uint32_t)temp - pgm_read_word(&(temptable[table_num][j-1][0]))) * pgm_read_word(&(temptable[table_num][j][1]))
								//                 +
									+
								//                   (x₁-x)
									(pgm_read_word(&(temptable[table_num][j][0])) - (uint32_t)temp)
								//                         y₀ )
									* pgm_read_word(&(temptable[table_num][j-1][1])))
								//                              /
									/
								//                                (x₁ - x₀)
									(pgm_read_word(&(temptable[table_num][j][0])) - pgm_read_word(&(temptable[table_num][j-1][0])));
								#ifndef	EXTRUDER
								if (debug_flags & DEBUG_PID)
									sersendf_P(PSTR(" temp:%d.%d"),temp/4,(temp%4)*25);
								#endif
								break;
							}
						}
						#ifndef	EXTRUDER
						if (debug_flags & DEBUG_PID)
							sersendf_P(PSTR(" Sensor:%d\n"),i);
						#endif


						//Clamp for overflows
						if (j == NUMTEMPS)
							temp = temptable[table_num][NUMTEMPS-1][1];

						temp_sensors_runtime[i].next_read_time = 0;
					} while (0);
					break;
				#endif	/* TEMP_THERMISTOR */

				#ifdef	TEMP_AD595
				case TT_AD595:
					temp = analog_read(temp_sensors[i].temp_pin);

					// convert
					// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
					temp = (temp * 500L) >> 8;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_AD595 */

				#ifdef	TEMP_PT100
				case TT_PT100:
					#warning TODO: PT100 code
					break
				#endif	/* TEMP_PT100 */

				#ifdef	TEMP_INTERCOM
				case TT_INTERCOM:
					temp = read_temperature(temp_sensors[i].temp_pin);

					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_INTERCOM */

				#ifdef	TEMP_DUMMY
				case TT_DUMMY:
					temp = temp_sensors_runtime[i].last_read_temp;

					if (temp_sensors_runtime[i].target_temp > temp)
						temp++;
					else if (temp_sensors_runtime[i].target_temp < temp)
						temp--;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_DUMMY */

				default: /* prevent compiler warning */
					break;
			}
			temp_sensors_runtime[i].last_read_temp = temp;

			if (labs((int16_t)(temp - temp_sensors_runtime[i].target_temp)) < (TEMP_HYSTERESIS*4)) {
				if (temp_sensors_runtime[i].temp_residency < (TEMP_RESIDENCY_TIME*100))
					temp_sensors_runtime[i].temp_residency++;
			}
			else {
				temp_sensors_runtime[i].temp_residency = 0;
			}

			if (temp_sensors[i].heater < NUM_HEATERS) {
				heater_tick(temp_sensors[i].heater, i, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp);
			}
		}
	}
示例#13
0
文件: main.c 项目: tcdog001/ptest
int main( int argc, char **argv )
{
    char ch;
    int serfd;
    char data[256];
    char recvdata[256];
    int length;
    int recvlength;
    int i;
    char cmdline[256];
    int ret;

    //调试输出单元
    tracePrintfInit();
    {
        //modifyTraceLevelByMode(SYS_MODE, DEBUG_TRACE);
        //modifyTraceLevelByMode(IMG_MODE, DEBUG_TRACE);
        //modifyTraceLevelByMode(FT_MODE, DEBUG_TRACE);
    }

    printf("begin integrate\n");

    serfd = InitSerialCom(2,115200,'n',1, 8);
    if (serfd == -1)
    {
        printf("COM2 open failure\n");
        return 0;
    }

    i = 0;
    while(1)
    {
        memset(data, 0, 256);
        sprintf(data, "hello\n");
        length = strlen(data);
        SerialSend(serfd, (unsigned char *)data, length);

        memset(recvdata, 0, 256);

        recvlength = serialReceive(serfd, recvdata, 256);
        if (recvlength)
        {
            printf("|%s|%d\n", recvdata, recvlength);
            if (recvlength == 2)
            {
                if (strncmp(recvdata, "ok", strlen("ok")) == 0)
                {
                    printf("COM2 OK\n");
                    break;

                }
            }

        }
        i++;

        if (i > 50)
        {
            printf("COM2 FAILURE\n");
            break;
        }

        usleep(1000*500);
    }

    while(1)
    {
        memset(cmdline, 0, 256);
        scanf("%s", cmdline);

        if (strncmp(cmdline, "getRTCTime", strlen("getRTCTime")) == 0)
        {
            memset(data, 0, 64);
            get_current_time_string(data);
        }
        else if (strncmp(cmdline, "setUSBTest", strlen("setUSBTest")) == 0)
        {
            ret = confirm_usb_running();
            if (ret)
            {
                printf("testUSBSuccess\n");
            }
            else
            {
                printf("testUSBFailure\n");
            }
        }
        else if (strncmp(cmdline, "getSN", strlen("getSN")) == 0)
        {
            memset(data, 0, 64);
            get_pcba_sn(data, 64);
            printf("reportSN|%s\n", data);
        }
        else if (strncmp(cmdline, "getMac", strlen("getMac")) == 0)
        {
            memset(data, 0, 64);
            get_pcba_mac(data, 64);
            printf("reportMAC|%s\n", data);
        }
        else if (strncmp(cmdline, "getMediaBoradTestReport", strlen("getMediaBoradTestReport")) == 0)
        {
            memset(data, 0, 64);
            get_pcba_idx99(data, 64);
            printf("reportMediaBoardTestInfo|%s\n", data);
        }

    }




#if 0
    char ch;

    //调试输出单元
    tracePrintfInit();
    {
        //modifyTraceLevelByMode(SYS_MODE, DEBUG_TRACE);
        //modifyTraceLevelByMode(IMG_MODE, DEBUG_TRACE);
        //modifyTraceLevelByMode(FT_MODE, DEBUG_TRACE);
    }

    init_display_output_device(FMT_1080P_60);

    init_framebuf_module();

    ft_Font_Init();
    init_temperature_module();
    sync_time_from_rtc();

    prepare_bg();
    /*
        system("mkdir -p /media");
        system("mkdir -p /media/tfcard");
        system("mkdir -p /media/usb");
        system("mkdir -p /media/msata");
    */
    init_hard_device_task();

    system("rm /tmp/leftai_ok /tmp/rightai_ok");
    system("/tmp/sample_ai >/tmp/ai.log &");
    display_welcom();

    usleep(3000*1000);
    //ai_display_filter(1);

    while(1)
    {
#if 1
        if ((access("/tmp/leftai_ok", F_OK) == 0) &&
                (access("/tmp/rightai_ok", F_OK) == 0))
        {
            usleep(1000*1000);
            break;
        }
#else

        if (access("/tmp/rightai_ok", F_OK) == 0)
        {
            break;
        }

#endif

        ai_display_filter(0);

        if (get_ai_force_exit())
        {
            break;
        }

        usleep(1000*1000);

    }

    if ((access("/tmp/leftai_ok", F_OK) == 0) &&
            (access("/tmp/rightai_ok", F_OK) == 0))
    {
        set_test_status(audio_ok);
    }

    ai_display_filter(1);
    system("touch /tmp/exit_ai");


    // printf("aaaaaaa\n");

    display_stb_info();

    usleep(500*1000);
    // printf("dddddd\n");



    series_display();
    usleep(500*1000);

    display_msata();
    usleep(500*1000);

    display_tfcard();
    usleep(500*1000);

    display_usb();
    usleep(500*1000);

    while(1)
    {

        if (test_flag & gpio_test)
        {
            display_gpio_test();
            break;
        }
        else
        {
            display_gpio_putdown();
        }


        if (get_force_exit_gpio())
        {
            printf("\nGPIO failure\n");
            break;
        }
        usleep(1000*1000);
    }

    save_test_status();
    exit_timer();


    usleep(500*1000);
    printf("\nvideo play\n");
    display_player();
    //save_test_status();

#if 1
    while(1)
    {
        ch = getchar();
        if (ch == 'q')
        {
            break;
        }
        else if (ch == 'w')
        {
            test_framebuf();
        }
        else if (ch == 'e')
        {
            clearFramebuf();
        }
        else if (ch == 'r')
        {
            Pixel64 *pCanvas;
            int width;
            int height;
            GrPos Pos;
            GrRegion Region;

            decJpgFile("/nfs/wait4open.jpg", &pCanvas, &height, &width);
            Pos.x = Pos.y = 0;
            Region.x = Region.y = 0;
            Region.w = width;
            Region.h = height;

            paint_canvas_2_background(pCanvas, Pos, Region);

            refresh_background_2_device(Pos, Region);
        }
        else if (ch == 't')
        {
            Pixel64 *pCanvas;
            int width;
            int height;
            GrPos Pos;
            GrRegion Region;
            decPngFile("/nfs/ico_dir.png", &pCanvas, &width, &height);

            Pos.x = 100;
            Pos.y = 100;
            Region.x = 0;
            Region.y = 0;
            Region.w = width;
            Region.h = height;

            paint_canvas_2_logic_device(pCanvas, Pos, Region);
            pCanvas = get_logic_canvas();
            move_region_2_display(pCanvas, Pos, Region);

        }
        else if (ch == 'y')
        {
            GrPos Pos;
            Pixel64 FT;

            Pos.x = 137;
            Pos.y = 102;
            FT.RGB.a = 0xFF;
            FT.RGB.r = 0xD7;
            FT.RGB.g = 0xD7;
            FT.RGB.b = 0xD7;

            ft_Font_Str2Disp("hello world", FT, Pos, 40);
        }
        else if (ch == 'u')
        {
            fprintf(stderr, "开始装备测试\n");
            set_test_network(0);
        }
        else if (ch == 'i')
        {
            confirm_network_running(0);
        }
        else if (ch == 'o')
        {
            float temp;

            temp = read_temperature();
            printf("temperature %3.4f\n", temp);
        }
        else if (ch == 'p')
        {
            save_time_into_rtc();
        }
        else if (ch == 'a')
        {
            sync_time_from_rtc();
        }
        else if (ch == 's')
        {
            int value40;
            int value41;
            int value44;

            read_gpio_status(40, &value40);
            read_gpio_status(41, &value41);
            read_gpio_status(44, &value44);
            printf("40 = %d, 41 = %d, 44 = %d\n", value40, value41, value44);
        }
        else if (ch == 'd')
        {
            write_gpio_status(44, 0);
        }
        else if (ch == 'f')
        {
            write_gpio_status(44, 1);
        }
        else if (ch == 'g')
        {
            fd_ser = InitSerialCom(1,115200,'n',1, 8);
        }
        else if (ch == 'h')
        {
            unsigned char data[10];
            sprintf(data, "hello");
            SerialSend(fd_ser, data, 5);
        }
        else if (ch == 'j')
        {
            unsigned char data[10];
            memset(data, 0, 10);
            serialReceive(fd_ser, data, 10);
            printf("data\n", data);
        }
        else if (ch == 'k')
        {
            get_system_time();
        }
        else if (ch == 'l')
        {
            Pixel64 *pcanvas;
            Pixel64 FT;
            int i, j;
            FILE *wfp;
            pcanvas = getFramebuf();

            wfp = fopen("/nfs/screen.raw", "wb");
            for (i = 0; i < 720; i++)
            {
                for (j = 0; j < 1280; j++)
                {

                    FT.RGB.r = pcanvas[j].RGB.r;
                    FT.RGB.b = pcanvas[j].RGB.b;
                    FT.RGB.a = pcanvas[j].RGB.a;
                    FT.RGB.g = pcanvas[j].RGB.g;

                    fwrite(&(FT.RGB.r), 1, 1, wfp);
                    fwrite(&(FT.RGB.g), 1, 1, wfp);
                    fwrite(&(FT.RGB.b), 1, 1, wfp);
                }
                pcanvas += 1280;
            }
            fclose(wfp);
        }

    }
#endif

    close_logic_framebuf_module();
    ft_Font_Destroy();

    close_display_output_device();

    return 0;
#endif

}
示例#14
0
/// called every 10ms from clock.c - check all temp sensors that are ready for checking
void temp_sensor_tick() {
	temp_sensor_t i = 0;
	for (; i < NUM_TEMP_SENSORS; i++) {
		if (temp_sensors_runtime[i].next_read_time) {
			temp_sensors_runtime[i].next_read_time--;
		}
		else {
			uint16_t	temp = 0;
			//time to deal with this temp sensor
			switch(temp_sensors[i].temp_type) {
				#ifdef	TEMP_MAX6675
				case TT_MAX6675:
					#ifdef	PRR
						PRR &= ~MASK(PRSPI);
					#elif defined PRR0
						PRR0 &= ~MASK(PRSPI);
					#endif

					SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);

					// enable TT_MAX6675
					WRITE(SS, 0);

					// No delay required, see
					// https://github.com/triffid/Teacup_Firmware/issues/22

					// read MSB
					SPDR = 0;
					for (;(SPSR & MASK(SPIF)) == 0;);
					temp = SPDR;
					temp <<= 8;

					// read LSB
					SPDR = 0;
					for (;(SPSR & MASK(SPIF)) == 0;);
					temp |= SPDR;

					// disable TT_MAX6675
					WRITE(SS, 1);

					temp_sensors_runtime[i].temp_flags = 0;
					if ((temp & 0x8002) == 0) {
						// got "device id"
						temp_sensors_runtime[i].temp_flags |= PRESENT;
						if (temp & 4) {
							// thermocouple open
							temp_sensors_runtime[i].temp_flags |= TCOPEN;
						}
						else {
							temp = temp >> 3;
						}
					}

					// this number depends on how frequently temp_sensor_tick is called. the MAX6675 can give a reading every 0.22s, so set this to about 250ms
					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_MAX6675	*/

				#ifdef	TEMP_THERMISTOR
				case TT_THERMISTOR:
					do {
						uint8_t j, table_num;
						//Read current temperature
						temp = analog_read(temp_sensors[i].temp_pin);
						// for thermistors the thermistor table number is in the additional field
						table_num = temp_sensors[i].additional;

						//Calculate real temperature based on lookup table
						for (j = 1; j < NUMTEMPS; j++) {
							if (pgm_read_word(&(temptable[table_num][j][0])) > temp) {
								// Thermistor table is already in 14.2 fixed point
								#ifndef	EXTRUDER
								if (DEBUG_PID && (debug_flags & DEBUG_PID))
									sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),temp_sensors[i].temp_pin,temp,j);
								#endif
								// Linear interpolating temperature value
								// y = ((x - x₀)y₁ + (x₁-x)y₀ ) / (x₁ - x₀)
								// y = temp
								// x = ADC reading
								// x₀= temptable[j-1][0]
								// x₁= temptable[j][0]
								// y₀= temptable[j-1][1]
								// y₁= temptable[j][1]
								// y =
								// Wikipedia's example linear interpolation formula.
								temp = (
								//     ((x - x₀)y₁
									((uint32_t)temp - pgm_read_word(&(temptable[table_num][j-1][0]))) * pgm_read_word(&(temptable[table_num][j][1]))
								//                 +
									+
								//                   (x₁-x)
									(pgm_read_word(&(temptable[table_num][j][0])) - (uint32_t)temp)
								//                         y₀ )
									* pgm_read_word(&(temptable[table_num][j-1][1])))
								//                              /
									/
								//                                (x₁ - x₀)
									(pgm_read_word(&(temptable[table_num][j][0])) - pgm_read_word(&(temptable[table_num][j-1][0])));
								#ifndef	EXTRUDER
								if (DEBUG_PID && (debug_flags & DEBUG_PID))
									sersendf_P(PSTR(" temp:%d.%d"),temp/4,(temp%4)*25);
								#endif
								break;
							}
						}
						#ifndef	EXTRUDER
						if (DEBUG_PID && (debug_flags & DEBUG_PID))
							sersendf_P(PSTR(" Sensor:%d\n"),i);
						#endif


						//Clamp for overflows
						if (j == NUMTEMPS)
							temp = temptable[table_num][NUMTEMPS-1][1];

						temp_sensors_runtime[i].next_read_time = 0;
					} while (0);
					break;
				#endif	/* TEMP_THERMISTOR */

				#ifdef	TEMP_AD595
				case TT_AD595:
					temp = analog_read(temp_sensors[i].temp_pin);

					// convert
					// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
					temp = (temp * 500L) >> 8;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_AD595 */

				#ifdef	TEMP_PT100
				case TT_PT100:
					#warning TODO: PT100 code
					break
				#endif	/* TEMP_PT100 */

				#ifdef	TEMP_INTERCOM
				case TT_INTERCOM:
					temp = read_temperature(temp_sensors[i].temp_pin);

					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_INTERCOM */

				#ifdef	TEMP_NONE
				case TT_NONE:
					temp_sensors_runtime[i].last_read_temp =
					  temp_sensors_runtime[i].target_temp; // for get_temp()
					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_NONE */

				#ifdef	TEMP_DUMMY
				case TT_DUMMY:
					temp = temp_sensors_runtime[i].last_read_temp;

					if (temp_sensors_runtime[i].target_temp > temp)
						temp++;
					else if (temp_sensors_runtime[i].target_temp < temp)
						temp--;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_DUMMY */

				default: /* prevent compiler warning */
					break;
			}
			temp_sensors_runtime[i].last_read_temp = temp;
		}
		if (labs((int16_t)(temp_sensors_runtime[i].last_read_temp - temp_sensors_runtime[i].target_temp)) < (TEMP_HYSTERESIS*4)) {
			if (temp_sensors_runtime[i].temp_residency < (TEMP_RESIDENCY_TIME*100))
				temp_sensors_runtime[i].temp_residency++;
		}
		else {
			temp_sensors_runtime[i].temp_residency = 0;
		}

		if (temp_sensors[i].heater < NUM_HEATERS) {
			heater_tick(temp_sensors[i].heater, temp_sensors[i].temp_type, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp);
		}
	}
int main(void)
{
	static uint8_t ret = 0;
	uint8_t i = 0;
	uint8_t ibuf[16] = {0};
	static uint8_t test_pattern[PATTERN_TEST_LENGTH];
	sensor_data_t sensor_data;
	twi_master_options_t opt;

	irq_initialize_vectors();

	sysclk_init();

	/* Initialize the board.
	 * The board-specific conf_board.h file contains the configuration of
	 * the board initialization.
	 */
	board_init();
	gfx_mono_init();
	ioport_set_pin_high(NHD_C12832A1Z_BACKLIGHT);
	gfx_mono_draw_string("Reading....\r\n", 0, 0, &sysfont);
	gfx_mono_generic_draw_filled_rect(0, 8, 128, 8, GFX_PIXEL_CLR);

	/* configure the pins connected to LEDs as output and set their default
	 * initial state to low (LEDs off).
	 */
	ioport_configure_pin(LED_LOW, IOPORT_DIR_OUTPUT);
	ioport_configure_pin(LED_HIGH, IOPORT_DIR_OUTPUT);
	ioport_configure_pin(LED_CRIT, IOPORT_DIR_OUTPUT);
	ioport_configure_pin(LED_NORM, IOPORT_DIR_OUTPUT);

	ioport_set_pin_low(LED_LOW);
	ioport_set_pin_low(LED_HIGH);
	ioport_set_pin_low(LED_CRIT);
	ioport_set_pin_low(LED_NORM);

	/* Configure the ALERT/EVENT pin which is
	 * routed to pin 2 of J2 on A3BU Xplained
	 * This pin can be used for polling or interrupt
	 */
	ioport_configure_pin(EVENT_PIN, IOPORT_DIR_INPUT);

	attach_device(EXAMPLE_TS_DEVICE_ADDR, EXAMPLE_TS_DEVICE);
	opt.chip = EXAMPLE_TS_DEVICE_ADDR;
	opt.speed = TWI_SPEED;

	/* Initialize TWI driver with options */
	twi_master_setup(TWI_MODULE, &opt);

	sensor_data.config_reg.value = 0;
	/* Set configuration register to 12-bis resolution */
	sensor_data.config_reg.option.RES  = AT30TS7_RES12;

	if (write_config(sensor_data.config_reg.value) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Set the polarity of ALERT/EVENT pin to low */

	if (set_config_option(&sensor_data, AT30TS_POL, AT30TS7_POL_ACTIVE_LOW) !=
	TWI_SUCCESS) {
	test_fail_indication();
	}

	/* Read the configuration register */
	if (read_config(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}

#if defined _AT30TS00_ || defined _AT30TSE002B_
	/* Set t_high limit register to +75.0000C */
	if (write_tcrit(pos, 75, 0000) != TWI_SUCCESS) {
		test_fail_indication();
	}
#endif

	/* Set t_high limit register to +50.7500C */
	if (write_temperature_high(pos, 50, 7500) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Set t_low limit register to -25.2500C */

	/*
	 * if (write_temperature_low(neg, 25, 2500)!= TWI_SUCCESS) {
	 * test_fail_indication();
	 * }
	 */

	/* Set t_low limit register to +35.5000C */
	if (write_temperature_low(pos, 35, 5000) != TWI_SUCCESS) {
		test_fail_indication();
	}

#if defined _AT30TS00_ || defined _AT30TSE002B_
	/* Read t_crit register register */
	if (read_tcrit(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}
#endif

	/* Read t_high limit register */
	if (read_temperature_high(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Read t_low register register */
	if (read_temperature_low(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Non volatile register functionality */
#if defined _AT30TS750_  || defined _AT30TSE752_ || \
	defined _AT30TSE754_ || defined _AT30TSE758_

	/* Copy volatile registers to nonvolatile registers
	 * vol configuration register  -> nonvol configuration register
	 * vol t_high register -> nonvol t_high register
	 * vol t_low  register -> nonvol t_low register
	 */
        ret = ts75_copy_vol_nonvol_register();
	if (ret != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Read the nonvol configuration register */
	if (read_nvconfig(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Read the nonvol t_high register */
	if (read_nvthigh(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Read the nonvol t_low register */
	if (read_nvtlow(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Clear vol configuration register */
	if (write_config(0x0000) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Read the vol configuration register */
	if (read_config(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Copy nonvolatile registers to volatile registers */
	if (ts75_copy_nonvol_vol_register() != TWI_SUCCESS) {
		test_fail_indication();
	}

	/* Read the configuration register */
	if (read_config(&sensor_data) != TWI_SUCCESS) {
		test_fail_indication();
	}
#endif
        /* To avoid 'variable unused' warning */
        test_pattern[0] = ibuf[0];
        ibuf[0] = test_pattern[0];

	/* EEPROM Test */
#if defined _AT30TSE002B_  || defined _AT30TSE752_ || \
	defined _AT30TSE754_   || defined _AT30TSE758_

	/* Generate Test Pattern */
	for (i = 0; i < PATTERN_TEST_LENGTH; i++) {
		test_pattern[i] = 0x41 + i; // 'ABCD...'
	}

	/* Perform a write access & check write result */
	if ((ret = ts_write_memory(EE_TEST_ADDR, PATTERN_TEST_LENGTH,
	(void *)test_pattern)) != TWI_SUCCESS) {
		gfx_mono_draw_string("EE Write Failed ", 0, 24, &sysfont);
		test_fail_indication();
	}

	/* Allow time for EEPROM to settle */
	delay_ms(5);
	/* Clear test_pattern */
	memset(ibuf, 0, sizeof(ibuf));

	/* Perform a read access & check read result */
	if (ts_read_eeprom(EE_TEST_ADDR, PATTERN_TEST_LENGTH,
			ibuf) != TWI_SUCCESS) {
		gfx_mono_draw_string("EE Read Failed ", 0, 24, &sysfont);
		test_fail_indication();
	}

	/* Check received data against sent data */
	for (i = 0; i < PATTERN_TEST_LENGTH; i++) {
		if (ibuf[i] != test_pattern[i]) {
			gfx_mono_draw_string("EE Read mismatch ", 0, 24,
				&sysfont);
			test_fail_indication();
		}
	}

	gfx_mono_draw_string("EE Write/Read OK", 0, 24, &sysfont);
	gfx_mono_draw_string((char const*)ibuf, 0, 16, &sysfont);
#endif
	/*
	 * Temperature reading contained in struct,i.e.
	 * temperature register value = 0x3240 (+50.25C), AT30TSE758 device
	 * sensor_data.temperature.itemp = 50 //!< integer part
	 * sensor_data.temperature.ftemp = 2500 //!< fractional part
	 * sensor_data.temperature.sign = 0 //!< sign (pos(+) = 0, neg(-) = 1)
	 * sensor_data.temperature.raw_value = 0x324 //!< raw data
	 */

	char senseData[50] = {0};
	while (1) {
		/* Read temperature */
		read_temperature(&sensor_data);
		sprintf(senseData, "%d.%04d DegC",
					sensor_data.temperature.itemp,
						sensor_data.temperature.ftemp);
		gfx_mono_draw_string(senseData, 0, 8, &sysfont);
		ioport_set_pin_low(LED_NORM);
		delay_ms(200);
		ioport_set_pin_high(LED_NORM);
		delay_ms(200);
	}
}
示例#16
0
main()
{ 
ds1307_init(); 

// Set date for -> 15 June 2005 Tuesday 
// Set time for -> 15:20:55 
//ds1307_set_date_time(18,11,12,2,22,05,55); 


  setup_adc(ADC_CLOCK_INTERNAL);
//enables the a/d module 
  set_adc_channel(0);
//the next read_adc call will read channel 0
  delay_us(10);
//a small delay is required after setting the channel

//aguarda 100ms
  delay_ms(100);

//inicializa o display LCD
  inic_display();

  while (true)
  {

    switch(tela){
      case 0:
        display(0,0x01);
        update_clock();
        read_temperature();
        check_temperature();
        show_temperature();
        show_clock();

        if(tecla_set_status && !tecla_menos_status && tecla_mais_status)
          tela = 2;

        if(tecla_set_status && tecla_menos_status && !tecla_mais_status)
          tela = 1;
        

        break;
      case 1:
        read_temperature();
        configure_temperature();
        break;
      case 2:
        //update_clock();
        configure_time();
        break;
    }

//alterna o estado do pino D4
    //output_toggle(PIN_D1);

    verifica_teclas();

//aguarda 500ms
    delay_ms (100);
  }
}
示例#17
0
void show_temperature_filter(void)
{
    static struct timeval cur_tm;
    unsigned int distms = 0;
    int ret;
    float temp;
    char data[64];
    GrPos Pos;
    static GrRegion Region = {0, 0, 500, 40};
    Pixel64 FT;
    static int tmperature_cnt = 0;

    /*
    if (tmperature_cnt > 3)
    {
        return ;
    }
    */

    gettimeofday(&cur_tm, NULL);

    distms = ((cur_tm.tv_sec*1000+(cur_tm.tv_usec)/1000)-(record_tm.tv_sec*1000+(record_tm.tv_usec)/1000));
    if (distms >= 1*1000)
    {
        memset(data, 0, 64);
        temp = read_temperature();
        if ((temp <= 24) ||
            (temp >= 60))
        {
            FT.RGB.a = 255;
            FT.RGB.r = 255;
            FT.RGB.g = 0;
            FT.RGB.b = 0;

            set_test_status(temperature_failure);
            if (tmperature_cnt == 3)
            {
                printf("\ntemperature failure\n");
            }
            tmperature_cnt++;
        }
        else
        {
            FT.RGB.a = 255;
            FT.RGB.r = 255;
            FT.RGB.g = 255;
            FT.RGB.b = 255;
            if (tmperature_cnt == 3)
            {
                printf("\ntemperature success\n");
            }
            tmperature_cnt ++;
        }

        if (tmperature_cnt > 4)
        {
            tmperature_cnt = 4;
        }

        if (tmperature_cnt == 3)
        {
            printf("temperature %3.4fC\n", temp);
        }

        sprintf(data, "temperature %3.4fC", temp);

        Pos.x = 590;
        Pos.y = 50;

        Region.x = Region.y = 0;
        Region.w = 400;
        Region.h = 40;
        refresh_background_2_device(Pos, Region);
        //printf("44444444444444444444444\n");
        ft_Font_Str2Disp_return_region(data,
            FT,
            Pos,
            35,
            &Region);

        //printf("55555555555555555555555\n");
        record_tm = cur_tm;
    }
}
void lcd_display_temperature()
{
          temperature =read_temperature();
          lcd_display(temperature,13,2);
}
示例#19
0
文件: airflow.c 项目: abelits/airflow
/*
 * main
 */
int main(int argc, char **argv)
{
  int configfile;
  int nlines, i, keyword;
  char *configfilename, *configbuffer, *p, **lines;
  int interval = 10;
  int dev_mismatch = 0;
  
  struct stat statbuf;

  /* Read configuration file. */
  if(argc > 1)
    configfilename = argv[1];
  else
    configfilename = "/etc/fancontrol";

  configfile = open(configfilename, O_RDONLY);
  if(configfile < 0)
    {
      perror(configfilename);
      return 1;
    }
  if(fstat(configfile, &statbuf) < 0)
    {
      perror(configfilename);
      close(configfile);
      return 1;
    }
  if(statbuf.st_size <= 0)
    {
      fprintf(stderr, "Configuration file %s is empty.\n", configfilename);
      close(configfile);
      return 1;
    }
  configbuffer = (char*) malloc(statbuf.st_size + 1);
  if(configbuffer == NULL)
    {
      fprintf(stderr, "Insufficient memory.\n");
      close(configfile);
      return 0;
    }
  if(read_whole_persist(configfile, configbuffer, statbuf.st_size) != statbuf.st_size)
    {
      fprintf(stderr,  "Can't read the configuration file %s.\n",
	      configfilename);
      close(configfile);
      return 1;
    }
  configbuffer[statbuf.st_size] = '\0';
  close(configfile);

  /* Parse configuration. */
  p = configbuffer;
  nlines = 1;
  while(*p)
    if(*p++ == '\n')
      nlines++;
  
  lines = (char**) malloc(nlines * sizeof(char*));
  if(lines == NULL)
    {
      fprintf(stderr, "Insufficient memory.\n");
      free(configbuffer);
      return 1;
    }

  for(p = configbuffer, i = 0; i < nlines ; i++)
    {
      lines[i] = p;
      p = strchr(p, '\n');
      if(p != NULL)
	*p++ = '\0';
    }

  /* Parse lines, create descriptors. */
  for(i = 0; i < nlines; i++)
    {
      p = strchr(lines[i], '#');
      if(p != NULL)
	*p = '\0';
      p = strchr(lines[i], '=');
      if(p != NULL)
	{
	  *p = '\0';
	  p++;
	  keyword = find_keyword(lines[i]);
	  switch(keyword)
	    {
	    case INTERVAL:
	      if((sscanf(p, "%i", &interval) != 1)
		 || (interval < 1)
		 || (interval > 100))
		interval = 10;
	      break;
	    case DEVPATH:
	      dev_mismatch |= check_devpaths(p);
	      break;
	    case DEVNAME:
	      dev_mismatch |= check_devnames(p);
	      break;
	    case FCTEMPS:
	      configure_fctemps(p);
	      break;
	    case FCFANS:
	      configure_fcfans(p);
	      break;
	    case MINTEMP:
	    case MAXTEMP:
		configure_common_param(p, keyword);
	      break;
	    case MINSTART:
	    case MINSTOP:
	    case MINPWM:
	    case MAXPWM:
	      configure_fan_control_param(p, keyword);
	      break;
	    }
	}
    }

  if(dev_mismatch)
    {
      fprintf(stderr, "Devices do not match saved paths and names, exiting.\n");
      return 1;
    }

  /*
    Do not try to run if configuration does not contain
    at least one sensor and at least one control.
  */
  if((temp_sensors_head == NULL) || (fan_controls_head == NULL))
    {
      fprintf(stderr, "No devices defined, exiting.\n");
      return 1;
    }

  /* Set handler for restoring the fans uncontrolled state */
  struct sigaction act;

  memset(&act, 0, sizeof(act));
  act.sa_handler = sighandler;

  sigaction(SIGTERM, &act, NULL);
  sigaction(SIGINT, &act, NULL);
  sigaction(SIGQUIT, &act, NULL);

  /* Enable fan control */
  struct fan_control *current_control;
  current_control = fan_controls_head;
  while(current_control)
    {
      fan_enable(current_control->address, 1);
      current_control = current_control->next;
    }

  /* Main loop. */
  while(running)
    {
      /* Read all temperatures. */
      struct temp_sensor *current_temp_sensor;
      current_temp_sensor = temp_sensors_head;
      while(current_temp_sensor)
	{
	  read_temperature(current_temp_sensor);
	  current_temp_sensor = current_temp_sensor->next;
	}
      
      /* Read all fan speeds */
      struct fan_sensor *current_fan_sensor;
      current_fan_sensor = fan_sensors_head;
      while(current_fan_sensor)
	{
	  read_fan_speed(current_fan_sensor);
	  current_fan_sensor = current_fan_sensor->next;
	}

      /* 
	 Read current PWM value for controls,
	 determine and set new PWM values.
      */
      current_control = fan_controls_head;
      while(current_control)
	{
	  int min_fan_speed, new_pwm;
	  read_fan_pwm(current_control);
	  min_fan_speed = get_min_fan_speed(current_control);
	  new_pwm = get_max_pwm_by_temperature(current_control);

	  /* Check if we are starting a stopped fan */
	  if((new_pwm > current_control->minpwm)
	    && ((min_fan_speed == 0) 
		|| (current_control->value <= current_control->minpwm)))
	    new_pwm = current_control->minstart;

	  /* Set new PWM if it changed */
	  if(new_pwm != current_control->value)
	    set_fan_pwm(current_control, new_pwm);
	  current_control = current_control->next;
	}
      sleep(interval);
    }

  /* Restore fans */
  restore_fans();
  return 0;
}
示例#20
0
文件: temp.c 项目: nmacs/print3d
/// called every 10ms from clock.c - check all temp sensors that are ready for checking
void temp_sensor_tick() {
	temp_sensor_t i = 0;
	for (; i < NUM_TEMP_SENSORS; i++) {
		if (temp_sensors_runtime[i].next_read_time) {
			temp_sensors_runtime[i].next_read_time--;
		}
		else {
			uint16_t	temp = 0;
			#ifdef	TEMP_MAX31855
			uint32_t value = 0;
			struct max31855_plat_data *max31855;
			#endif
			//time to deal with this temp sensor
			switch(temp_sensors[i].temp_type) {
				#ifdef	TEMP_MAX31855
				case TT_MAX31855:
				#ifdef __arm__
				        max31855 = (struct max31855_plat_data*)temp_sensors[i].plat_data;
					spiAcquireBus(max31855->bus);
					spiStart(max31855->bus, max31855->config);
					spiSelect(max31855->bus);
					spiReceive(max31855->bus, 4, &value);
					spiUnselect(max31855->bus);
					spiReleaseBus(max31855->bus);

					value = SWAP_UINT32(value);

					temp_sensors_runtime[i].temp_flags = 0;
					if (value & (1 << 16)) {
                                        #ifdef HALT_ON_TERMOCOUPLE_FAILURE
						emergency_stop();
                                        #endif
					}
					else {
						temp = value >> 18;
						if (temp & (1 << 13))
							temp = 0;
					}
				#else
					temp = 0;
				#endif

					break;
				#endif
				#ifdef	TEMP_MAX6675
				case TT_MAX6675:
					#ifdef	PRR
						PRR &= ~MASK(PRSPI);
					#elif defined PRR0
						PRR0 &= ~MASK(PRSPI);
					#endif

					SPCR = MASK(MSTR) | MASK(SPE) | MASK(SPR0);

					// enable TT_MAX6675
					WRITE(SS, 0);

					// No delay required, see
					// https://github.com/triffid/Teacup_Firmware/issues/22

					// read MSB
					SPDR = 0;
					for (;(SPSR & MASK(SPIF)) == 0;);
					temp = SPDR;
					temp <<= 8;

					// read LSB
					SPDR = 0;
					for (;(SPSR & MASK(SPIF)) == 0;);
					temp |= SPDR;

					// disable TT_MAX6675
					WRITE(SS, 1);

					temp_sensors_runtime[i].temp_flags = 0;
					if ((temp & 0x8002) == 0) {
						// got "device id"
						temp_sensors_runtime[i].temp_flags |= PRESENT;
						if (temp & 4) {
							// thermocouple open
							temp_sensors_runtime[i].temp_flags |= TCOPEN;
						}
						else {
							temp = temp >> 3;
						}
					}

					// this number depends on how frequently temp_sensor_tick is called. the MAX6675 can give a reading every 0.22s, so set this to about 250ms
					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_MAX6675	*/

				#ifdef	TEMP_THERMISTOR
				case TT_THERMISTOR:
					do {
						uint8_t j, table_num;
						//Read current temperature
						temp = analog_read(i);
						// for thermistors the thermistor table number is in the additional field
						table_num = temp_sensors[i].additional;

						//Calculate real temperature based on lookup table
						for (j = 1; j < NUMTEMPS; j++) {
							if (pgm_read_word(&(temptable[table_num][j][0])) > temp) {
								// Thermistor table is already in 14.2 fixed point
								#ifndef	EXTRUDER
								if (DEBUG_PID && (debug_flags & DEBUG_PID))
									sersendf_P(PSTR("pin:%d Raw ADC:%d table entry: %d"),temp_sensors[i].temp_pin,temp,j);
								#endif
								// Linear interpolating temperature value
								// y = ((x - x₀)y₁ + (x₁-x)y₀ ) / (x₁ - x₀)
								// y = temp
								// x = ADC reading
								// x₀= temptable[j-1][0]
								// x₁= temptable[j][0]
								// y₀= temptable[j-1][1]
								// y₁= temptable[j][1]
								// y =
								// Wikipedia's example linear interpolation formula.
								temp = (
								//     ((x - x₀)y₁
									((uint32_t)temp - pgm_read_word(&(temptable[table_num][j-1][0]))) * pgm_read_word(&(temptable[table_num][j][1]))
								//                 +
									+
								//                   (x₁-x)
									(pgm_read_word(&(temptable[table_num][j][0])) - (uint32_t)temp)
								//                         y₀ )
									* pgm_read_word(&(temptable[table_num][j-1][1])))
								//                              /
									/
								//                                (x₁ - x₀)
									(pgm_read_word(&(temptable[table_num][j][0])) - pgm_read_word(&(temptable[table_num][j-1][0])));
								#ifndef	EXTRUDER
								if (DEBUG_PID && (debug_flags & DEBUG_PID))
									sersendf_P(PSTR(" temp:%d.%d"),temp/4,(temp%4)*25);
								#endif
								break;
							}
						}
						#ifndef	EXTRUDER
						if (DEBUG_PID && (debug_flags & DEBUG_PID))
							sersendf_P(PSTR(" Sensor:%d\n"),i);
						#endif


						//Clamp for overflows
						if (j == NUMTEMPS)
							temp = temptable[table_num][NUMTEMPS-1][1];

						temp_sensors_runtime[i].next_read_time = 0;
					} while (0);
					break;
				#endif	/* TEMP_THERMISTOR */

				#ifdef	TEMP_AD595
				case TT_AD595:
					temp = analog_read(i);

					// convert
					// >>8 instead of >>10 because internal temp is stored as 14.2 fixed point
					temp = (temp * 500L) >> 8;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_AD595 */

				#ifdef	TEMP_PT100
				case TT_PT100:
					#warning TODO: PT100 code
					break
				#endif	/* TEMP_PT100 */

				#ifdef	TEMP_INTERCOM
				case TT_INTERCOM:
					temp = read_temperature(temp_sensors[i].temp_pin);

					temp_sensors_runtime[i].next_read_time = 25;

					break;
				#endif	/* TEMP_INTERCOM */

				#ifdef	TEMP_DUMMY
				case TT_DUMMY:
					temp = temp_sensors_runtime[i].last_read_temp;

					if (temp_sensors_runtime[i].target_temp > temp)
						temp++;
					else if (temp_sensors_runtime[i].target_temp < temp)
						temp--;

					temp_sensors_runtime[i].next_read_time = 0;

					break;
				#endif	/* TEMP_DUMMY */

				default: /* prevent compiler warning */
					break;
			}
			/* Exponentially Weighted Moving Average alpha constant for smoothing
			   noisy sensors. Instrument Engineer's Handbook, 4th ed, Vol 2 p126
			   says values of 0.05 to 0.1 for TEMP_EWMA are typical. */
			#ifndef TEMP_EWMA
				#define TEMP_EWMA 1.0
			#endif
			#define EWMA_SCALE  1024L
			#define EWMA_ALPHA  ((long) (TEMP_EWMA * EWMA_SCALE))
			temp_sensors_runtime[i].last_read_temp = (uint16_t) ((EWMA_ALPHA * temp +
			  (EWMA_SCALE-EWMA_ALPHA) * temp_sensors_runtime[i].last_read_temp
			                                         ) / EWMA_SCALE);
		}
		if (labs((int16_t)(temp_sensors_runtime[i].last_read_temp - temp_sensors_runtime[i].target_temp)) < (TEMP_HYSTERESIS*4)) {
			if (temp_sensors_runtime[i].temp_residency < (TEMP_RESIDENCY_TIME*120))
				temp_sensors_runtime[i].temp_residency++;
		}
		else {
			// Deal with flakey sensors which occasionally report a wrong value
			// by setting residency back, but not entirely to zero.
			if (temp_sensors_runtime[i].temp_residency > 10)
				temp_sensors_runtime[i].temp_residency -= 10;
			else
				temp_sensors_runtime[i].temp_residency = 0;
		}

		if (temp_sensors[i].heater < NUM_HEATERS) {
			heater_tick(temp_sensors[i].heater, temp_sensors[i].temp_type, temp_sensors_runtime[i].last_read_temp, temp_sensors_runtime[i].target_temp);
		}

    if (DEBUG_PID && (debug_flags & DEBUG_PID))
      sersendf_P(PSTR("DU temp: {%d %d %d.%d}"), i,
                 temp_sensors_runtime[i].last_read_temp,
                 temp_sensors_runtime[i].last_read_temp / 4,
                 (temp_sensors_runtime[i].last_read_temp & 0x03) * 25);
	}