示例#1
0
文件: mixer.c 项目: 4712/cleanflight
float convertExternalToMotor(uint16_t externalValue)
{
    uint16_t motorValue;
    switch ((int)isMotorProtocolDshot()) {
#ifdef USE_DSHOT
    case true:
        externalValue = constrain(externalValue, PWM_RANGE_MIN, PWM_RANGE_MAX);

        if (feature(FEATURE_3D)) {
            if (externalValue == PWM_RANGE_MID) {
                motorValue = DSHOT_DISARM_COMMAND;
            } else if (externalValue < PWM_RANGE_MID) {
                motorValue = scaleRange(externalValue, PWM_RANGE_MIN, PWM_RANGE_MID - 1, DSHOT_3D_DEADBAND_LOW, DSHOT_MIN_THROTTLE);
            } else {
                motorValue = scaleRange(externalValue, PWM_RANGE_MID + 1, PWM_RANGE_MAX, DSHOT_3D_DEADBAND_HIGH, DSHOT_MAX_THROTTLE);
            }
        } else {
            motorValue = (externalValue == PWM_RANGE_MIN) ? DSHOT_DISARM_COMMAND : scaleRange(externalValue, PWM_RANGE_MIN + 1, PWM_RANGE_MAX, DSHOT_MIN_THROTTLE, DSHOT_MAX_THROTTLE);
        }

        break;
    case false:
#endif
    default:
        motorValue = externalValue;
        break;
    }

    return (float)motorValue;
}
示例#2
0
文件: mixer.c 项目: 4712/cleanflight
uint16_t convertMotorToExternal(float motorValue)
{
    uint16_t externalValue;
    switch ((int)isMotorProtocolDshot()) {
#ifdef USE_DSHOT
    case true:
        if (feature(FEATURE_3D)) {
            if (motorValue == DSHOT_DISARM_COMMAND || motorValue < DSHOT_MIN_THROTTLE) {
                externalValue = PWM_RANGE_MID;
            } else if (motorValue <= DSHOT_3D_DEADBAND_LOW) {
                externalValue = scaleRange(motorValue, DSHOT_MIN_THROTTLE, DSHOT_3D_DEADBAND_LOW, PWM_RANGE_MID - 1, PWM_RANGE_MIN);
            } else {
                externalValue = scaleRange(motorValue, DSHOT_3D_DEADBAND_HIGH, DSHOT_MAX_THROTTLE, PWM_RANGE_MID + 1, PWM_RANGE_MAX);
            }
        } else {
            externalValue = (motorValue < DSHOT_MIN_THROTTLE) ? PWM_RANGE_MIN : scaleRange(motorValue, DSHOT_MIN_THROTTLE, DSHOT_MAX_THROTTLE, PWM_RANGE_MIN + 1, PWM_RANGE_MAX);
        }
        break;
    case false:
#endif
    default:
        externalValue = motorValue;
        break;
    }

    return externalValue;
}
	//scales a number using different scales depending if num is greater or less than the zero point oldZero.
	//if hardCutoff is true, it will not exceed the extrema
	double SensorOutput::scaleWeightedRange(double num, double oldMin, double oldZero, double oldMax, double newMin, double newMax, bool hardCutoff) {
	  double newZero = scaleRange(0.5, 0, 1, newMin, newMax);

	  if (num > oldZero) 
	    return scaleRange(num, oldZero, oldMax, newZero, newMax, hardCutoff);
	  else
	    return scaleRange(num, oldMin, oldZero, newMin, newZero, hardCutoff);
	}
示例#4
0
static void applyLedFixedLayers()
{
    for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
        const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[ledIndex];
        hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND);

        int fn = ledGetFunction(ledConfig);
        int hOffset = HSV_HUE_MAX;

        switch (fn) {
            case LED_FUNCTION_COLOR:
                color = ledStripConfig()->colors[ledGetColor(ledConfig)];
                break;

            case LED_FUNCTION_FLIGHT_MODE:
                for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++)
                    if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) {
                        const hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &ledStripConfig()->modeColors[flightModeToLed[i].ledMode]);
                        if (directionalColor) {
                            color = *directionalColor;
                        }

                        break; // stop on first match
                    }
                break;

            case LED_FUNCTION_ARM_STATE:
                color = ARMING_FLAG(ARMED) ? *getSC(LED_SCOLOR_ARMED) : *getSC(LED_SCOLOR_DISARMED);
                break;

            case LED_FUNCTION_BATTERY:
                color = HSV(RED);
                hOffset += scaleRange(calculateBatteryPercentage(), 0, 100, -30, 120);
                break;

            case LED_FUNCTION_RSSI:
                color = HSV(RED);
                hOffset += scaleRange(rssi * 100, 0, 1023, -30, 120);
                break;

            default:
                break;
        }

        if (ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) {
            hOffset += scaledAux;
        }

        color.h = (color.h + hOffset) % (HSV_HUE_MAX + 1);

        setLedHsv(ledIndex, &color);

    }
}
示例#5
0
void ledStripUpdate(timeUs_t currentTimeUs)
{
    if (!(ledStripInitialised && isWS2811LedStripReady())) {
        return;
    }

    if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(ledStripConfig()->ledstrip_visual_beeper && isBeeperOn())) {
        if (ledStripEnabled) {
            ledStripDisable();
            ledStripEnabled = false;
        }
        return;
    }
    ledStripEnabled = true;

    const uint32_t now = currentTimeUs;

    // test all led timers, setting corresponding bits
    uint32_t timActive = 0;
    for (timId_e timId = 0; timId < timTimerCount; timId++) {
        // sanitize timer value, so that it can be safely incremented. Handles inital timerVal value.
        const timeDelta_t delta = cmpTimeUs(now, timerVal[timId]);
        // max delay is limited to 5s
        if (delta < 0 && delta > -MAX_TIMER_DELAY)
            continue;  // not ready yet
        timActive |= 1 << timId;
        if (delta >= 100 * 1000 || delta < 0) {
            timerVal[timId] = now;
        }
    }

    if (!timActive)
        return;          // no change this update, keep old state

    // apply all layers; triggered timed functions has to update timers

    scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, 100) : 0;
    scaledAux = scaleRange(rcData[ledStripConfig()->ledstrip_aux_channel], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1);

    applyLedFixedLayers();

    for (timId_e timId = 0; timId < ARRAYLEN(layerTable); timId++) {
        uint32_t *timer = &timerVal[timId];
        bool updateNow = timActive & (1 << timId);
        (*layerTable[timId])(updateNow, timer);
    }
    ws2811UpdateStrip();
}
示例#6
0
void mavlinkSendRCChannelsAndRSSI(void)
{
    uint16_t msgLength;
    mavlink_msg_rc_channels_raw_pack(0, 200, &mavMsg,
        // time_boot_ms Timestamp (milliseconds since system boot)
        millis(),
        // port Servo output port (set of 8 outputs = 1 port). Most MAVs will just use one, but this allows to encode more than 8 servos.
        0,
        // chan1_raw RC channel 1 value, in microseconds
        (rxRuntimeConfig.channelCount >= 1) ? rcData[0] : 0,
        // chan2_raw RC channel 2 value, in microseconds
        (rxRuntimeConfig.channelCount >= 2) ? rcData[1] : 0,
        // chan3_raw RC channel 3 value, in microseconds
        (rxRuntimeConfig.channelCount >= 3) ? rcData[2] : 0,
        // chan4_raw RC channel 4 value, in microseconds
        (rxRuntimeConfig.channelCount >= 4) ? rcData[3] : 0,
        // chan5_raw RC channel 5 value, in microseconds
        (rxRuntimeConfig.channelCount >= 5) ? rcData[4] : 0,
        // chan6_raw RC channel 6 value, in microseconds
        (rxRuntimeConfig.channelCount >= 6) ? rcData[5] : 0,
        // chan7_raw RC channel 7 value, in microseconds
        (rxRuntimeConfig.channelCount >= 7) ? rcData[6] : 0,
        // chan8_raw RC channel 8 value, in microseconds
        (rxRuntimeConfig.channelCount >= 8) ? rcData[7] : 0,
        // rssi Receive signal strength indicator, 0: 0%, 255: 100%
        scaleRange(rssi, 0, 1023, 0, 255));
    msgLength = mavlink_msg_to_send_buffer(mavBuffer, &mavMsg);
    mavlinkSerialWrite(mavBuffer, msgLength);
}
示例#7
0
void osdUpdateFCState(void)
{
    fcStatus.vbat = vbat;
    fcStatus.fcState = packFlightModeFlags();
    fcStatus.rssi = scaleRange(rssi, 0, 1023, 0, 1000);

}
示例#8
0
文件: osd.c 项目: Ralfde/betaflight
static char osdGetBatterySymbol(int cellVoltage)
{
    if (getBatteryState() == BATTERY_CRITICAL) {
        return SYM_MAIN_BATT; // FIXME: currently the BAT- symbol, ideally replace with a battery with exclamation mark
    } else {
        // Calculate a symbol offset using cell voltage over full cell voltage range
        const int symOffset = scaleRange(cellVoltage, batteryConfig()->vbatmincellvoltage * 10, batteryConfig()->vbatmaxcellvoltage * 10, 0, 7);
        return SYM_BATT_EMPTY - constrain(symOffset, 0, 6);
    }
}
示例#9
0
uint8_t LeftRightTiltColorGenerator::chooseColorIndex(int16_t axisValue, int axisMin, int axisMax, uint8_t colorsInPalette) {

	//Serial.println(sensorDataStore.sampledAccelerationData.x, DEC);
	int16_t limitedAxisValue = axisValue;
	if (limitedAxisValue < axisMin) {
		limitedAxisValue = axisMin;
	} else if (limitedAxisValue > axisMax) {
		limitedAxisValue = axisMax;
	}
	return (uint8_t) scaleRange(limitedAxisValue, axisMin, axisMax, 0, colorsInPalette - 1);
}
示例#10
0
文件: rx.c 项目: budebulai/SkyoverCF
STATIC_UNIT_TESTED uint16_t applyRxChannelRangeConfiguraton(int sample, rxChannelRangeConfiguration_t range)
{
    // Avoid corruption of channel with a value of PPM_RCVR_TIMEOUT
    if (sample == PPM_RCVR_TIMEOUT) {
        return PPM_RCVR_TIMEOUT;
    }

    sample = scaleRange(sample, range.min, range.max, PWM_RANGE_MIN, PWM_RANGE_MAX);
    sample = MIN(MAX(PWM_PULSE_MIN, sample), PWM_PULSE_MAX);

    return sample;
}
示例#11
0
void osdElementRender_motors(const element_t *element, elementDataProviderFn dataFn)
{
    uint16_t *motors = (uint16_t *) dataFn();

    const int maxMotors = 4; // just quad for now
    for (int i = 0; i < maxMotors; i++) {
        if (!motors[i]) {
            continue; // skip unused/uninitialsed motors.
        }
        int percent = scaleRange(motors[i], 1000, 2000, 0, 100); // FIXME should use min/max command as used by the FC.

        osdHardwareDisplayMotor(quadMotorCoordinateOffsets[i].x + element->x, quadMotorCoordinateOffsets[i].y + element->y, percent);
    }
}
示例#12
0
void MovingRainbowAnimation::frameBegin(void) {
  xOffset = 0;
  yOffset = 0;

  int16_t limitedAxisValue = sensorDataStore.sampledAccelerationData.x;
  if (limitedAxisValue < AXIS_X_MIN) {
    limitedAxisValue = AXIS_X_MIN;
  } else if (limitedAxisValue > AXIS_X_MAX) {
    limitedAxisValue = AXIS_X_MAX;
  }
  int temp = scaleRange(limitedAxisValue, AXIS_X_MIN, AXIS_X_MAX, 0 - MAX_RAINBOW_FRAME_DELAY_MS, MAX_RAINBOW_FRAME_DELAY_MS);

  additionalFrameDelay = (MAX_RAINBOW_FRAME_DELAY_MS - abs(temp)) * 1000L;

  framePercent = ((uint32_t)frameCounter * 100) / totalFrames;
}
示例#13
0
void updateLedStrip(void)
{
    if (!(ledStripInitialised && isWS2811LedStripReady())) {
        return;
    }

    if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(masterConfig.ledstrip_visual_beeper && isBeeperOn())) {
        if (ledStripEnabled) {
            ledStripDisable();
            ledStripEnabled = false;
        }
        return;
    }
    ledStripEnabled = true;

    uint32_t now = micros();

    // test all led timers, setting corresponding bits
    uint32_t timActive = 0;
    for (timId_e timId = 0; timId < timTimerCount; timId++) {
        // sanitize timer value, so that it can be safely incremented. Handles inital timerVal value.
        // max delay is limited to 5s
        int32_t delta = cmp32(now, timerVal[timId]);
        if (delta < 0 && delta > -LED_STRIP_MS(5000))
            continue;  // not ready yet
        timActive |= 1 << timId;
        if (delta >= LED_STRIP_MS(100) || delta < 0) {
            timerVal[timId] = now;
        }
    }

    if (!timActive)
        return;          // no change this update, keep old state

    // apply all layers; triggered timed functions has to update timers

    scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 10, 100) : 10;

    applyLedFixedLayers();

    for (timId_e timId = 0; timId < ARRAYLEN(layerTable); timId++) {
        uint32_t *timer = &timerVal[timId];
        bool updateNow = timActive & (1 << timId);
        (*layerTable[timId])(updateNow, timer);
    }
    ws2811UpdateStrip();
}
示例#14
0
void sendRcDataToHid(void)
{
    int8_t report[8];
    for (unsigned i = 0; i < USB_CDC_HID_NUM_AXES; i++) {
        const uint8_t channel = hidChannelMapping[i];
        report[i] = scaleRange(constrain(rcData[channel], PWM_RANGE_MIN, PWM_RANGE_MAX), PWM_RANGE_MIN, PWM_RANGE_MAX, USB_CDC_HID_RANGE_MIN, USB_CDC_HID_RANGE_MAX);
        if (i == 1) {
            // For some reason ROLL is inverted in Windows
            report[i] = -report[i];
        }
    }
#if defined(STM32F4)
    USBD_HID_SendReport(&USB_OTG_dev, (uint8_t*)report, sizeof(report));
#elif defined(STM32F7)
    USBD_HID_SendReport(&USBD_Device, (uint8_t*)report, sizeof(report));
#else
# error "MCU does not support USB HID."
#endif
}
示例#15
0
void applyLedThrottleLayer()
{
    const ledConfig_t *ledConfig;
    hsvColor_t color;

    uint8_t ledIndex;
    for (ledIndex = 0; ledIndex < ledCount; ledIndex++) {
        ledConfig = &ledConfigs[ledIndex];
        if (!(ledConfig->flags & LED_FUNCTION_THROTTLE)) {
            continue;
        }

        getLedHsv(ledIndex, &color);

        int scaled = scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, -60, +60);
        scaled += HSV_HUE_MAX;
        color.h = (color.h + scaled) % HSV_HUE_MAX;
        setLedHsv(ledIndex, &color);
    }
}
示例#16
0
// return positive for ACK, negative on error
int mspClientReplyHandler(mspPacket_t *reply)
{
    sbuf_t * src = &reply->buf;
    int len = sbufBytesRemaining(src);

    mspClientStatus.lastReplyAt = micros();

    UNUSED(len);

    switch (reply->cmd) {
        case MSP_STATUS:
            fcStatus.cycleTime = sbufReadU16(src);
            fcStatus.i2cErrors = sbufReadU16(src);
            fcStatus.sensors = sbufReadU16(src);
            fcStatus.fcState = sbufReadU32(src);
            fcStatus.profile = sbufReadU8(src);
        break;

        case MSP_ANALOG:
            fcStatus.vbat = sbufReadU8(src);
            fcStatus.mAhDrawn = sbufReadU16(src);
            fcStatus.rssi = scaleRange(sbufReadU16(src), 0, 1023, 0, 1000);
            fcStatus.amperage = sbufReadU16(src);
            break;

        case MSP_MOTOR:
            for (unsigned i = 0; i < 8 && i < OSD_MAX_MOTORS; i++) {
                fcMotors[i] = sbufReadU16(src);
            }
        break;

        default:
            // we do not know how to handle the message
            return -1;
    }
    return 1;
}
示例#17
0
void Animator::calculateValueAxisPositionsForSource(ValueAxisSource *valueAxisSource, int16_t rawValue, int16_t rangeMin, int16_t rangeMax) {


#ifdef DEBUG_VALUE_AXIS_POSITIONS
    Serial.print("Value Axis Positions (index,low,high) (value,position): ");
#endif

    int16_t clampedValue = max(rangeMin, min(rangeMax, rawValue));

    for (uint8_t valueAxisIndex = 0; valueAxisIndex < valueAxisCount; valueAxisIndex++) {
        ValueAxis *valueAxis = valueAxes[valueAxisIndex];

        int8_t position = scaleRange(clampedValue, rangeMin, rangeMax, valueAxis->valueAxisLowValue, valueAxis->valueAxisHighValue);
        valueAxisSource->applyValueAxisPosition(valueAxisIndex, position);

#ifdef DEBUG_VALUE_AXIS_POSITIONS
        if (valueAxisIndex != 0) {
            Serial.print(", ");
        }
        Serial.print("(");
        Serial.print(valueAxisIndex, DEC);
        Serial.print(",");
        Serial.print(valueAxis->valueAxisLowValue, DEC);
        Serial.print(",");
        Serial.print(valueAxis->valueAxisLowValue, DEC);
        Serial.print(") (");
        Serial.print(value, DEC);
        Serial.print(",");
        Serial.print(valueAxisPositions[valueAxisIndex], DEC);
        Serial.print(")");
#endif
    }
#ifdef DEBUG_VALUE_AXIS_POSITIONS
    Serial.println();
#endif
}
示例#18
0
VOID OnPaint(HWND hWnd, HDC hdc)
{
	Graphics graphics(hdc);
	Pen      pen(Color::Red);
	Pen axis(Color::Black);
	Pen power(Color::Blue);
	Pen green(Color::Green);
	
	memblock* mem = w.next(audio.framesAvailable());
	audio.fillBuffer();
	//graphics.Clear(Color::White);
	
	if (w.hasNext() && beats[(mem->p-w.get_data_p())/(w.getH()->wBitsPerSample/8)/(w.getH()->nChannels)/bd.getPrecision()] != false)
	{
		RECT rect;
		rect.left = 0;
		rect.top = 0;
		rect.right = scrW;
		rect.bottom = scrH;
		DrawText(hdc, _T("BEAT"), -1, &rect, DT_CENTER);
	}
	else graphics.Clear(Color::White);
	
	if (mem->nBytes == 0) return;
	return;	//Comment this to enable sound wave rendering

	graphics.Clear(Color::White);
	graphics.DrawLine(&axis, 0, scrH / 2, scrW, scrH / 2);
	graphics.DrawLine(&axis, scrW / 2, 0, scrW / 2, scrH);

	int bps = (w.getH()->wBitsPerSample / 8);
	
	byte* u = (byte*)mem->p;

	int px = 0;
	double py;
	
	int newy;
	for (unsigned int i = 0; i < mem->nBytes; i+=w.getH()->nChannels*bps)
	{
		switch (bps)
		{
		case 1:
			newy = (int)(scrH / 2 + scaleRange(*(int8_t*)(u + i), INT8_MIN, INT8_MAX, -scrH/2, scrH/2));
			break;
		case 2:
			newy = (int)(scrH / 2 + scaleRange(*(int16_t*)(u + i), INT16_MIN, INT16_MAX, -scrH / 2, scrH / 2));
			break;
		case 3:
			newy = (int)(scrH / 2 + scaleRange((*(int24*)(u + i)).data, -pow(2, 23), pow(2, 23), -scrH / 2, scrH / 2));
			break;
		case 4:
			newy = (int)(scrH / 2 + scaleRange(*(int32_t*)(u + i), INT32_MIN, INT32_MAX, -scrH / 2, scrH / 2));
			break;
		}
		newy += scrH / 2;
		if (i == 0) py = newy;
		graphics.DrawLine(&pen, px, (int)py, px + 1, newy);
		py = newy;
		px++;
	}

	//memblock bpmmem;
	//bpmmem.p = (uintptr_t)w.get_data_p();
	//bpmmem.nBytes = w.get_data_size();
	//int bpm = w.detectBPM(bpmmem, 60, 180, 10);

	//std::wstringstream sstream;
	//sstream << bpm;
	//MessageBox(hWnd, sstream.str().c_str(), L"BPM", MB_SYSTEMMODAL);

	//w.DFTWindow(*mem, Wave::DFTWindowType::Hanning);


	//DFTransform* dft = w.DFT(*mem);

	//DFTransform::DFTChannelResult* dftr;

//	FFTransform* fft = w.FFT(*mem);
//
//	FFTransform::DFTChannelResult* dftr;
//
//	int prev = 0;
//	int previ = 0;
//
//	for (int i = 0; i < scrW; i++)
//	{
//		//dftr = &(dft->next(DFTransform::nextResult::STEREO)->stereo);
//		dftr = &(fft->next(FFTransform::nextResult::STEREO)->stereo);
//		if (dftr == nullptr) return;
//		if (i == 1)
//		{
//			freqdiff = dftr->freq;
//			
//		}
//
//
//		//Spectral magnitude in dB
//		//even function
//		int val = 1 * (dftr->dbmag);
//		if (i != 0)graphics.DrawLine(&power, i - 1, prev, i, scrH/2 - val);
//		else graphics.DrawLine(&power, i - 1, scrH/2 - val, i, scrH/2 - val);
//		prev = scrH/2 - val;
//
//		//angle
//		//odd function
//		int vali = radiansToDegrees(dftr->angle);
//		if (i != 0)graphics.DrawLine(&green, i - 1, previ, i, scrH / 2 - vali);
//		else graphics.DrawLine(&green, i - 1, scrH / 2 - previ, i, scrH / 2 - vali);
//		previ = scrH / 2 - vali;
//
///*
//		graphics.DrawLine(&power, i, scrH, i, scrH - 100*dftr->real);
//		graphics.DrawLine(&green, i, scrH, i, scrH - 100*dftr->imag);*/
//	}
//	delete fft;
//	//delete dft;
}
	//sets the input value, and
	//calculates the output value based on slider and cuttoff settings
	//value should ALWAYS be between 0 and 1
	void SensorOutput::setValue(double val) {
		//DEBUG_PRINT_NUM("SensorOutput::setValue ", val)
	
		//invert
		if (isInvert)
			val = 1.0 - val;


		//save cur raw val
		_inputValue = val;
		_outputValue = val;


		//calculate values!!!!!!
		//if (inRange == NULL) 
		//	return;

		// scale raw data into acceptable values between 0 and 1.
		_outputValue = scaleRange(_outputValue, inRange.low, inRange.high, 0., 1.);
		
		// boost that f****r
		if (isLogarithmic) {
			_outputValue = log10(_outputValue) + 1.0;
		}

		// now cut it down
		if (cutoffTypeVal == CUTOFF_TYPE_VAL_HARD) {
			if (_outputValue > cutoffRange.high)
				_outputValue = 1.0;
			else if (_outputValue < cutoffRange.low)
				_outputValue = 0.0;
		}
		else if (	cutoffTypeVal == (CUTOFF_TYPE_VAL_NULLABLE) ||
					cutoffTypeVal == (CUTOFF_TYPE_VAL_NULLABLE_LOW)) {
			if (_outputValue > cutoffRange.high ) {

				// special case if we want to capture the hard hits
				if (cutoffTypeVal == (CUTOFF_TYPE_VAL_NULLABLE_LOW)) {
					_outputValue = cutoffRange.high;
				}
				else {
					_outputValue = SensorizerServer::SENSOR_VALUE_NULL;
				}

			}
			else if (_outputValue < cutoffRange.low)
				_outputValue = SensorizerServer::SENSOR_VALUE_NULL;
		}		
		else if (cutoffTypeVal == (CUTOFF_TYPE_VAL_CLIP)) {
			if (_outputValue > cutoffRange.high)
				_outputValue = cutoffRange.high;
			else if (_outputValue < cutoffRange.low)
				_outputValue = cutoffRange.low;			
		}
		
		else { //NONE
			
			
		}
		
		//DEBUG_PRINT_NUM("SensorOutput::.outputFiltersCurlength ", outputFiltersCurlength)
		//synchronized(outputFilters) { 
			for (int i = 0; i < outputFiltersCurlength; i++) {
				//if (outputFilters[i] != NULL) {		
					outputFilters[i]->setValue(_outputValue);	
					_outputValue = outputFilters[i]->value();	
				//}
			}
		//}
		
		//TODO: equaitons should go here but out meters need to accept any num

		//EQUATIONS
		if (_outputValue != SensorizerServer::SENSOR_VALUE_NULL) {
			_outputValue = scaleRange(_outputValue, 0., 1., outRange.low, outRange.high);

			// for midi, it doesn't make sense to go above 1, but we'll leave this here for legacy support.
			_outputValue = _outputValue * multiplyVal + addVal;
		}
		
		//DEBUG_PRINT_NUM("DONE SensorOutput::setValue ", _outputValue)
	}
	//scales a number to fit within the new extrema.
	double SensorOutput::scaleRange(double num, double oldMin, double oldMax, double newMin, double newMax) {

		return scaleRange(num, oldMin, oldMax, newMin, newMax, false);
	}
示例#21
0
STATIC_UNIT_TESTED void servoMixer(void)
{
    int16_t input[INPUT_SOURCE_COUNT]; // Range [-500:+500]
    static int16_t currentOutput[MAX_SERVO_RULES];
    uint8_t i;

    if (FLIGHT_MODE(PASSTHRU_MODE)) {
        // Direct passthru from RX
        input[INPUT_STABILIZED_ROLL] = rcCommand[ROLL];
        input[INPUT_STABILIZED_PITCH] = rcCommand[PITCH];
        input[INPUT_STABILIZED_YAW] = rcCommand[YAW];
    } else {
        // Assisted modes (gyro only or gyro+acc according to AUX configuration in Gui
        input[INPUT_STABILIZED_ROLL] = axisPID[ROLL];
        input[INPUT_STABILIZED_PITCH] = axisPID[PITCH];
        input[INPUT_STABILIZED_YAW] = axisPID[YAW];

        // Reverse yaw servo when inverted in 3D mode
        if (feature(FEATURE_3D) && (rcData[THROTTLE] < rxConfig->midrc)) {
            input[INPUT_STABILIZED_YAW] *= -1;
        }
    }

    input[INPUT_GIMBAL_PITCH] = scaleRange(attitude.values.pitch, -1800, 1800, -500, +500);
    input[INPUT_GIMBAL_ROLL] = scaleRange(attitude.values.roll, -1800, 1800, -500, +500);

    input[INPUT_STABILIZED_THROTTLE] = motor[0] - 1000 - 500;  // Since it derives from rcCommand or mincommand and must be [-500:+500]

    // center the RC input value around the RC middle value
    // by subtracting the RC middle value from the RC input value, we get:
    // data - middle = input
    // 2000 - 1500 = +500
    // 1500 - 1500 = 0
    // 1000 - 1500 = -500
    input[INPUT_RC_ROLL]     = rcData[ROLL]     - rxConfig->midrc;
    input[INPUT_RC_PITCH]    = rcData[PITCH]    - rxConfig->midrc;
    input[INPUT_RC_YAW]      = rcData[YAW]      - rxConfig->midrc;
    input[INPUT_RC_THROTTLE] = rcData[THROTTLE] - rxConfig->midrc;
    input[INPUT_RC_AUX1]     = rcData[AUX1]     - rxConfig->midrc;
    input[INPUT_RC_AUX2]     = rcData[AUX2]     - rxConfig->midrc;
    input[INPUT_RC_AUX3]     = rcData[AUX3]     - rxConfig->midrc;
    input[INPUT_RC_AUX4]     = rcData[AUX4]     - rxConfig->midrc;

    for (i = 0; i < MAX_SUPPORTED_SERVOS; i++)
        servo[i] = 0;

    // mix servos according to rules
    for (i = 0; i < servoRuleCount; i++) {
        // consider rule if no box assigned or box is active
        if (currentServoMixer[i].box == 0 || IS_RC_MODE_ACTIVE(BOXSERVO1 + currentServoMixer[i].box - 1)) {
            uint8_t target = currentServoMixer[i].targetChannel;
            uint8_t from = currentServoMixer[i].inputSource;
            uint16_t servo_width = servoConf[target].max - servoConf[target].min;
            int16_t min = currentServoMixer[i].min * servo_width / 100 - servo_width / 2;
            int16_t max = currentServoMixer[i].max * servo_width / 100 - servo_width / 2;

            if (currentServoMixer[i].speed == 0)
                currentOutput[i] = input[from];
            else {
                if (currentOutput[i] < input[from])
                    currentOutput[i] = constrain(currentOutput[i] + currentServoMixer[i].speed, currentOutput[i], input[from]);
                else if (currentOutput[i] > input[from])
                    currentOutput[i] = constrain(currentOutput[i] - currentServoMixer[i].speed, input[from], currentOutput[i]);
            }

            servo[target] += servoDirection(target, from) * constrain(((int32_t)currentOutput[i] * currentServoMixer[i].rate) / 100, min, max);
        } else {
            currentOutput[i] = 0;
        }
    }

    for (i = 0; i < MAX_SUPPORTED_SERVOS; i++) {
        servo[i] = ((int32_t)servoConf[i].rate * servo[i]) / 100L;
        servo[i] += determineServoMiddleOrForwardFromChannel(i);
    }
}
示例#22
0
void updateLedStrip(void)
{

	if (!(ledStripInitialised && isWS2811LedStripReady())) {
        return;
    }

    if (IS_RC_MODE_ACTIVE(BOXLEDLOW)) {
        if (ledStripEnabled) {
            ledStripDisable();
            ledStripEnabled = false;
        }
    } else {
        ledStripEnabled = true;
    }
    
    if (!ledStripEnabled){
        return;
    }
    

    uint32_t now = micros();

    bool indicatorFlashNow = (int32_t)(now - nextIndicatorFlashAt) >= 0L;
    bool warningFlashNow = (int32_t)(now - nextWarningFlashAt) >= 0L;
    bool rotationUpdateNow = (int32_t)(now - nextRotationUpdateAt) >= 0L;
#ifdef USE_LED_ANIMATION
    bool animationUpdateNow = (int32_t)(now - nextAnimationUpdateAt) >= 0L;
#endif
    if (!(
            indicatorFlashNow ||
            rotationUpdateNow ||
            warningFlashNow
#ifdef USE_LED_ANIMATION
            || animationUpdateNow
#endif
    )) {
        return;
    }

    static uint8_t indicatorFlashState = 0;

    // LAYER 1
    applyLedModeLayer();
    applyLedThrottleLayer();

    // LAYER 2

    if (warningFlashNow) {
        nextWarningFlashAt = now + LED_STRIP_10HZ;
    }
    applyLedWarningLayer(warningFlashNow);

    // LAYER 3

    if (indicatorFlashNow) {

        uint8_t rollScale = ABS(rcCommand[ROLL]) / 50;
        uint8_t pitchScale = ABS(rcCommand[PITCH]) / 50;
        uint8_t scale = MAX(rollScale, pitchScale);
        nextIndicatorFlashAt = now + (LED_STRIP_5HZ / MAX(1, scale));

        if (indicatorFlashState == 0) {
            indicatorFlashState = 1;
        } else {
            indicatorFlashState = 0;
        }
    }

    applyLedIndicatorLayer(indicatorFlashState);

#ifdef USE_LED_ANIMATION
    if (animationUpdateNow) {
        nextAnimationUpdateAt = now + LED_STRIP_20HZ;
        updateLedAnimationState();
    }
    applyLedAnimationLayer();
#endif

    if (rotationUpdateNow) {

        applyLedThrustRingLayer();

        uint8_t animationSpeedScale = 1;

        if (ARMING_FLAG(ARMED)) {
            animationSpeedScale = scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 1, 10);
        }

        nextRotationUpdateAt = now + LED_STRIP_5HZ/animationSpeedScale;
    }

    ws2811UpdateStrip();
}
示例#23
0
void mavlinkSendHUDAndHeartbeat(void)
{
    uint16_t msgLength;
    float mavAltitude = 0;
    float mavGroundSpeed = 0;
    float mavAirSpeed = 0;
    float mavClimbRate = 0;

#if defined(GPS)
    // use ground speed if source available
    if (sensors(SENSOR_GPS)) {
        mavGroundSpeed = GPS_speed / 100.0f;
    }
#endif

    // select best source for altitude
#if defined(BARO) || defined(SONAR)
    if (sensors(SENSOR_SONAR) || sensors(SENSOR_BARO)) {
        // Baro or sonar generally is a better estimate of altitude than GPS MSL altitude
        mavAltitude = altitudeHoldGetEstimatedAltitude() / 100.0;
    }
#if defined(GPS)
    else if (sensors(SENSOR_GPS)) {
        // No sonar or baro, just display altitude above MLS
        mavAltitude = GPS_altitude;
    }
#endif
#elif defined(GPS)
    if (sensors(SENSOR_GPS)) {
        // No sonar or baro, just display altitude above MLS
        mavAltitude = GPS_altitude;
    }
#endif

    mavlink_msg_vfr_hud_pack(0, 200, &mavMsg,
        // airspeed Current airspeed in m/s
        mavAirSpeed,
        // groundspeed Current ground speed in m/s
        mavGroundSpeed,
        // heading Current heading in degrees, in compass units (0..360, 0=north)
        DECIDEGREES_TO_DEGREES(attitude.values.yaw),
        // throttle Current throttle setting in integer percent, 0 to 100
        scaleRange(constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX), PWM_RANGE_MIN, PWM_RANGE_MAX, 0, 100),
        // alt Current altitude (MSL), in meters, if we have sonar or baro use them, otherwise use GPS (less accurate)
        mavAltitude,
        // climb Current climb rate in meters/second
        mavClimbRate);
    msgLength = mavlink_msg_to_send_buffer(mavBuffer, &mavMsg);
    mavlinkSerialWrite(mavBuffer, msgLength);


    uint8_t mavModes = MAV_MODE_FLAG_MANUAL_INPUT_ENABLED;
    if (ARMING_FLAG(ARMED))
        mavModes |= MAV_MODE_FLAG_SAFETY_ARMED;

    uint8_t mavSystemType;
    switch(mixerConfig()->mixerMode)
    {
        case MIXER_TRI:
            mavSystemType = MAV_TYPE_TRICOPTER;
            break;
        case MIXER_QUADP:
        case MIXER_QUADX:
        case MIXER_Y4:
        case MIXER_VTAIL4:
            mavSystemType = MAV_TYPE_QUADROTOR;
            break;
        case MIXER_Y6:
        case MIXER_HEX6:
        case MIXER_HEX6X:
            mavSystemType = MAV_TYPE_HEXAROTOR;
            break;
        case MIXER_OCTOX8:
        case MIXER_OCTOFLATP:
        case MIXER_OCTOFLATX:
            mavSystemType = MAV_TYPE_OCTOROTOR;
            break;
        case MIXER_FLYING_WING:
        case MIXER_AIRPLANE:
        case MIXER_CUSTOM_AIRPLANE:
            mavSystemType = MAV_TYPE_FIXED_WING;
            break;
        case MIXER_HELI_120_CCPM:
        case MIXER_HELI_90_DEG:
            mavSystemType = MAV_TYPE_HELICOPTER;
            break;
        default:
            mavSystemType = MAV_TYPE_GENERIC;
            break;
    }

    // Custom mode for compatibility with APM OSDs
    uint8_t mavCustomMode = 1;  // Acro by default

    if (FLIGHT_MODE(ANGLE_MODE) || FLIGHT_MODE(HORIZON_MODE)) {
        mavCustomMode = 0;      //Stabilize
        mavModes |= MAV_MODE_FLAG_STABILIZE_ENABLED;
    }
    if (FLIGHT_MODE(BARO_MODE) || FLIGHT_MODE(SONAR_MODE))
        mavCustomMode = 2;      //Alt Hold
    if (FLIGHT_MODE(GPS_HOME_MODE))
        mavCustomMode = 6;      //Return to Launch
    if (FLIGHT_MODE(GPS_HOLD_MODE))
        mavCustomMode = 16;     //Position Hold (Earlier called Hybrid)

    uint8_t mavSystemState = 0;
    if (ARMING_FLAG(ARMED)) {
        if (failsafeIsActive()) {
            mavSystemState = MAV_STATE_CRITICAL;
        }
        else {
            mavSystemState = MAV_STATE_ACTIVE;
        }
    }
    else {
        mavSystemState = MAV_STATE_STANDBY;
    }

    mavlink_msg_heartbeat_pack(0, 200, &mavMsg,
        // type Type of the MAV (quadrotor, helicopter, etc., up to 15 types, defined in MAV_TYPE ENUM)
        mavSystemType,
        // autopilot Autopilot type / class. defined in MAV_AUTOPILOT ENUM
        MAV_AUTOPILOT_GENERIC,
        // base_mode System mode bitfield, see MAV_MODE_FLAGS ENUM in mavlink/include/mavlink_types.h
        mavModes,
        // custom_mode A bitfield for use for autopilot-specific flags.
        mavCustomMode,
        // system_status System status flag, see MAV_STATE ENUM
        mavSystemState);
    msgLength = mavlink_msg_to_send_buffer(mavBuffer, &mavMsg);
    mavlinkSerialWrite(mavBuffer, msgLength);
}
示例#24
0
static void applyLedFixedLayers(void)
{
    for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
        const ledConfig_t *ledConfig = &ledStripConfig()->ledConfigs[ledIndex];
        hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND);

        int fn = ledGetFunction(ledConfig);
        int hOffset = HSV_HUE_MAX + 1;

        switch (fn) {
        case LED_FUNCTION_COLOR:
            color = ledStripConfig()->colors[ledGetColor(ledConfig)];

            hsvColor_t nextColor = ledStripConfig()->colors[(ledGetColor(ledConfig) + 1 + LED_CONFIGURABLE_COLOR_COUNT) % LED_CONFIGURABLE_COLOR_COUNT];
            hsvColor_t previousColor = ledStripConfig()->colors[(ledGetColor(ledConfig) - 1 + LED_CONFIGURABLE_COLOR_COUNT) % LED_CONFIGURABLE_COLOR_COUNT];

            if (ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) {   //smooth fade with selected Aux channel of all HSV values from previousColor through color to nextColor
                int centerPWM = (PWM_RANGE_MIN + PWM_RANGE_MAX) / 2;
                if (auxInput < centerPWM) {
                    color.h = scaleRange(auxInput, PWM_RANGE_MIN, centerPWM, previousColor.h, color.h);
                    color.s = scaleRange(auxInput, PWM_RANGE_MIN, centerPWM, previousColor.s, color.s);
                    color.v = scaleRange(auxInput, PWM_RANGE_MIN, centerPWM, previousColor.v, color.v);
                } else {
                    color.h = scaleRange(auxInput, centerPWM, PWM_RANGE_MAX, color.h, nextColor.h);
                    color.s = scaleRange(auxInput, centerPWM, PWM_RANGE_MAX, color.s, nextColor.s);
                    color.v = scaleRange(auxInput, centerPWM, PWM_RANGE_MAX, color.v, nextColor.v);
                }
            }

            break;

        case LED_FUNCTION_FLIGHT_MODE:
            for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++)
                if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) {
                    const hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &ledStripConfig()->modeColors[flightModeToLed[i].ledMode]);
                    if (directionalColor) {
                        color = *directionalColor;
                    }

                    break; // stop on first match
                }
            break;

        case LED_FUNCTION_ARM_STATE:
            color = ARMING_FLAG(ARMED) ? *getSC(LED_SCOLOR_ARMED) : *getSC(LED_SCOLOR_DISARMED);
            break;

        case LED_FUNCTION_BATTERY:
            color = HSV(RED);
            hOffset += scaleRange(calculateBatteryPercentageRemaining(), 0, 100, -30, 120);
            break;

        case LED_FUNCTION_RSSI:
            color = HSV(RED);
            hOffset += scaleRange(getRssi() * 100, 0, 1023, -30, 120);
            break;

        default:
            break;
        }

        if ((fn != LED_FUNCTION_COLOR) && ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) {
            hOffset += scaleRange(auxInput, PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1);
        }

        color.h = (color.h + hOffset) % (HSV_HUE_MAX + 1);
        setLedHsv(ledIndex, &color);
    }
}
示例#25
0
void Animator::readAndSetColour(uint16_t ledIndex) {
    
    uint8_t red = animationReader->readUnsignedByte();
    uint8_t green = animationReader->readUnsignedByte();
    uint8_t blue = animationReader->readUnsignedByte();


#ifdef DEBUG_ANIMATOR_CODEC_LED_COLOURS
    if (DEBUG_LED_INDEX_TEST) {
        Serial.print("led colors (ledIndex) (r,g,b): (");
        Serial.print(ledIndex, DEC);
        Serial.print(") (0x");
        Serial.print(red, HEX);
        Serial.print(",0x");
        Serial.print(green, HEX);
        Serial.print(",0x");
        Serial.print(blue, HEX);
        Serial.println(")");
    }
#endif

#ifdef HACK_MIRROR_LEDS
    uint8_t row = ledIndex / (LEDS_PER_STRIP / 2);
    uint8_t column = ledIndex % (LEDS_PER_STRIP / 2);
    uint16_t mirrorIndex = (row * LEDS_PER_STRIP) + column;
#endif

    if (hasBackgroundColour &&
    	(
    		red == backgroundColourRed &&
    		green == backgroundColourGreen &&
    		blue == backgroundColourBlue
    	)
    ) {
#ifdef HACK_MIRROR_LEDS
        leds.setPixel(mirrorIndex, red, green, blue);
        leds.setPixel(mirrorIndex + (LEDS_PER_STRIP / 2), red, green, blue);
#else
        leds.setPixel(ledIndex, red, green, blue);
#endif
        return;
    }

    int32_t redIncrement = 0;
    int32_t greenIncrement = 0;
    int32_t blueIncrement = 0;

    for (uint8_t valueAxisIndex = 0; valueAxisIndex < valueAxisCount; valueAxisIndex++) {
        ValueAxis *currentValueAxis = valueAxes[valueAxisIndex];

        int8_t valueAxisPosition = determineValueAxisPosition(currentValueAxis, valueAxisIndex);

        int8_t start = 0;
        int8_t end = 0;
        if (valueAxisPosition < 0) {
            start = valueAxisPosition;
            end = currentValueAxis->valueAxisCentreValue;
        } else if (valueAxisPosition > 0) {
            start = currentValueAxis->valueAxisCentreValue + 1;
            end = valueAxisPosition + 1;
        }

#ifdef DEBUG_ANIMATOR_CODEC_VALUE_AXIS
        if (DEBUG_LED_INDEX_TEST) {
            Serial.print("led valueAxis (index,position) (start,end): (");
            Serial.print(valueAxisIndex, DEC);
            Serial.print(",");
            Serial.print(valueAxisPosition, DEC);
            Serial.print(") (");
            Serial.print(start, DEC);
            Serial.print(",");
            Serial.print(end, DEC);
            Serial.println(")");

            Serial.print("led increments (functionIndex) (r,g,b): ");
        }
#endif

        for (int8_t valueAxisValue = start; valueAxisValue < end; valueAxisValue++) {

            uint8_t functionIndex = currentValueAxis->retrieveFunctionIndex(ledIndex, valueAxisValue);

            int32_t *componentFunctionData = functionData[functionIndex];

            redIncrement += componentFunctionData[0];
            greenIncrement += componentFunctionData[1];
            blueIncrement += componentFunctionData[2];

#ifdef DEBUG_ANIMATOR_CODEC_VALUE_AXIS
            if (DEBUG_LED_INDEX_TEST) {
                if (valueAxisValue != start) {
                    Serial.print(", ");
                }
                Serial.print("(");
                Serial.print(functionIndex, DEC);
                Serial.print(") (");
                Serial.print(redIncrement, DEC);
                Serial.print(",");
                Serial.print(greenIncrement, DEC);
                Serial.print(",");
                Serial.print(blueIncrement, DEC);
                Serial.print(")");
            }
#endif
        }

#ifdef DEBUG_ANIMATOR_CODEC_VALUE_AXIS
        if (DEBUG_LED_INDEX_TEST) {
            Serial.println();
        }
#endif

#ifdef DEBUG_ANIMATOR_CODEC_FINAL_INCREMENTS
        if (DEBUG_LED_INDEX_TEST) {
            Serial.print("led pre-fixed increments (r,g,b): (");

            Serial.print(redIncrement, DEC);
            Serial.print(",");
            Serial.print(greenIncrement, DEC);
            Serial.print(",");
            Serial.print(blueIncrement, DEC);
            Serial.println(")");
        }
#endif

        redIncrement = fixIncrement(redIncrement);
        greenIncrement = fixIncrement(greenIncrement);
        blueIncrement = fixIncrement(blueIncrement);

#ifdef DEBUG_ANIMATOR_CODEC_FINAL_INCREMENTS
        if (DEBUG_LED_INDEX_TEST) {
            Serial.print("led post-fixed increments (r,g,b): (");

            Serial.print(redIncrement, DEC);
            Serial.print(",");
            Serial.print(greenIncrement, DEC);
            Serial.print(",");
            Serial.print(blueIncrement, DEC);
            Serial.println(")");
        }
#endif
    }

    red = applyIncrement(red, redIncrement);
    green = applyIncrement(green, greenIncrement);
    blue = applyIncrement(blue, blueIncrement);

#ifdef DEBUG_ANIMATOR_CODEC_LED_COLOURS
    if (DEBUG_LED_INDEX_TEST) {
        Serial.print("led final color: (ledIndex) (r,g,b): (");
        Serial.print(ledIndex, DEC);
        Serial.print(") (0x");
        Serial.print(red, HEX);
        Serial.print(",0x");
        Serial.print(green, HEX);
        Serial.print(",0x");
        Serial.print(blue, HEX);
        Serial.println(")");
    }
#endif

#ifdef APPLY_BRIGHTNESS_HACK
    red = scaleRange(red, 0x00, 0xff, 0x00, BRIGHTNESS_MAX);
    green = scaleRange(green, 0x00, 0xff, 0x00, BRIGHTNESS_MAX);
    blue = scaleRange(blue, 0x00, 0xff, 0x00, BRIGHTNESS_MAX);
#endif
    
#ifdef HACK_MIRROR_LEDS
    leds.setPixel(mirrorIndex, red, green, blue);
    leds.setPixel(mirrorIndex + (LEDS_PER_STRIP / 2), red, green, blue);
#else
    leds.setPixel(ledIndex, red, green, blue);
#endif
}