Beispiel #1
0
void Atomizer_ReadInfo(Atomizer_Info_t *info) {
	uint32_t vSum, iSum;
	uint16_t savedTargetVolts = 0;
	uint8_t wasOff = 0, numSamples, i;

	if(Atomizer_curState == POWEROFF) {
		// Power on at 1.00V for measurement
		wasOff = 1;
		savedTargetVolts = Atomizer_targetVolts;
		Atomizer_SetOutputVoltage(1000);
		Atomizer_Control(1);
		Timer_DelayMs(2);
	}

	// Sample V and I
	vSum = iSum = 0;
	numSamples = wasOff ? 50 : 1;
	for(i = 0; i < numSamples; i++) {
		Timer_DelayUs(10);
		iSum += ADC_Read(ADC_MODULE_CURS);
		Timer_DelayUs(10);
		vSum += ADC_Read(ADC_MODULE_VATM);
	}

	info->resistance = ATOMIZER_ADC_RESISTANCE(vSum, iSum);

	if(wasOff) {
		info->voltage = info->current = 0;

		// Power off and restore previous target voltage
		Atomizer_Control(0);
		Atomizer_SetOutputVoltage(savedTargetVolts);
	}
	else {
		info->voltage = ATOMIZER_ADC_VOLTAGE(vSum);
		info->current = ATOMIZER_ADC_CURRENT(iSum);
	}
}
Beispiel #2
0
void tempFire() {
    if (timerIndex == -1)
        timerIndex = requestTimerSlot();

    setTarget(s.targetTemperature);
    initPid();

    uint16_t newVolts = g.volts;
    int pidactive = 0;
    start = uptime;
    atTemp = 0;

    uint32_t nextFire = uptime;

#ifdef PROFILING
    uint32_t beforeFire, afterFire,
             beforeScreenUpdate, afterScreenUpdate,
             beforeDumpPid, afterDumpPid,
             beforeTunePid, afterTunePid;
    uint32_t FireAve = 0, ScreenAve = 0, DumpPidAve = 0, TunePidAve = 0;
    uint32_t loopCnt = 0;
#endif

    requestTimer(timerIndex, TimerHighRes);
    waitForFasterTimer(TimerHighRes);

#ifdef PROFILING
    writeUsb("Fire\tScreen\tDumpPid\tTunePid\r\n");
#endif

    while (gv.fireButtonPressed) {

#ifdef PROFILING
        loopCnt++;
        beforeFire = uptime;
#endif
        // < 1ms
        if (uptime > nextFire) {
            nextFire += FIREPERIOD;

            if (!Atomizer_IsOn() && g.atomInfo.resistance != 0
                && Atomizer_GetError() == OK) {
                // Power on
                Atomizer_Control(1);
            }

            // Update info
            // If resistance is zero voltage will be zero
            Atomizer_ReadInfo(&g.atomInfo);
            uint32_t sampled = uptime;
            EstimateCoilTemp();

            if (pidactive)
                g.watts = getNext(g.curTemp, sampled);

#ifdef PROFILING
            beforeTunePid = uptime;
#endif
            // < 1ms ave
            if (uptime + 1 < nextFire) {
                if (s.tunePids) {
                    if (1) {
                            writeUsb("%ld,%d,%ld,%ld,%ld,%lld,%ld,%ld,%ld\r\n",
                                      s.targetTemperature, g.curTemp,
                                      I.P, I.Error, I.I, I.AveError,
                                      I.D, I.DiffError, g.watts);
                    }
                }
            }
#ifdef PROFILING
            afterTunePid = uptime;
#endif

            // While the coil is 'cold', bad things can happen if you try to
            // Push it too hard.  Don't consider kicking it up until we've at
            // least reached 150C
            if (g.curTemp > 150) {
                if (!pidactive) {
                    if (s.targetTemperature - g.curTemp >= s.pidSwitch) {
                        g.watts = s.initWatts;
                    } else {
                        if (s.dumpPids) {
                            char b[63];
                            siprintf(b, "INFO,Switching to PID %" PRId32 " %d\r\n", s.targetTemperature, g.curTemp);
                            USB_VirtualCOM_SendString(b);
                        }
                        pidactive = 1;
                    }
                }
            }

            /*  TODO: Maybe make this baseRes dependant
            // Don't allow firing > 1 ohm in temp mode.
            if (g.atomInfo.resistance > 1000) {
                g.watts = 0;
            }
            */

            if (g.watts <= 1000)
                g.watts = 1000;

            if (g.watts > 100000) // Pid probably went c-razy on us, so drop watts.
                g.watts = 1000;

            if (g.watts > MAXWATTS)
                g.watts = MAXWATTS;

            newVolts = wattsToVolts(g.watts, g.atomInfo.resistance);
        }



        if (newVolts != g.volts) {
            uint16_t tNewVolts = newVolts;

            if (Atomizer_IsOn()) {
                // Update output voltage to correct res variations:
                // If the new voltage is lower, we only correct it in
                // 10mV steps, otherwise a flake res reading might
                // make the voltage plummet to zero and stop.
                // If the new voltage is higher, we push it up by 100mV
                // to make it hit harder on TC coils, but still keep it
                // under control.
                if (tNewVolts < g.volts) {
                    uint16_t dV = (g.volts - tNewVolts);
                    tNewVolts = g.volts - ( dV >= 75 ? 75 : dV);
                } else {
                    uint16_t dV = (tNewVolts - g.volts);
                    tNewVolts = g.volts + ( dV >= 75 ? 75 : dV);
                }
            }

            if (tNewVolts > MAXVOLTS) {
                tNewVolts = MAXVOLTS;
            }

            g.volts = tNewVolts;

            Atomizer_SetOutputVoltage(g.volts);
        }


#ifdef PROFILING
        afterFire = beforeScreenUpdate = uptime;
#endif
        // 7ms ave
        if (uptime + 7 < nextFire) {
            if (1) {// Update Screen Interval
                updateScreen(&g);

                if (s.stealthMode) {
                    /* GROSS hack to fix stealthmode */
                    uint32_t b = uptime;
                    do {;} while (b == uptime);
                }
            }
        }

#ifdef PROFILING
        afterScreenUpdate = beforeDumpPid = uptime;
#endif
        // <1ms ave
        if (uptime + 1 < nextFire) {
            if (1) { // dumpPids interval
                if (s.dumpPids) {
                     char buff[63];
                     siprintf(buff, "PID,%"PRId32",%d,%"PRIu32",%d\r\n",
                              s.targetTemperature,
                              g.curTemp,
                              g.watts,
                          g.atomInfo.resistance);
                     USB_VirtualCOM_SendString(buff);
                 }
             }
        }

#ifdef PROFILING
        afterDumpPid = uptime;
        writeUsb(UPTIME"\t"UPTIME"\t"UPTIME"\t"UPTIME"\r\n",
                                             TIMEFMT(afterFire - beforeFire),
                                             TIMEFMT(afterScreenUpdate - beforeScreenUpdate),
                                             TIMEFMT(afterDumpPid - beforeDumpPid),
                                             TIMEFMT(afterTunePid - beforeTunePid));
        FireAve += afterFire - beforeFire;
        ScreenAve += afterScreenUpdate - beforeScreenUpdate;
        DumpPidAve += afterDumpPid - beforeDumpPid;
        TunePidAve += afterTunePid - beforeTunePid;
#endif
    }
#ifdef PROFILING
    writeUsb(UPTIME"\t"UPTIME"\t"UPTIME"\t"UPTIME"\r\n",
                                             TIMEFMT(FireAve / loopCnt),
                                             TIMEFMT(ScreenAve / loopCnt),
                                             TIMEFMT(DumpPidAve / loopCnt),
                                             TIMEFMT(TunePidAve / loopCnt));
#endif
    requestTimer(timerIndex, TimerIdle);

    if (Atomizer_IsOn())
        Atomizer_Control(0);
}