The sumoeyes zones are documented here:
http://www.mindsensors.com/index.php?mo ... ile_id=863
Each zone is 20 degrees wide. It 0 degrees is straight ahead then the front zone is 350 (aka -10) to +10 degrees. The left zone is from 330 to 350 degrees. The right zone is from 10 to 30 degrees. Short range is up to 6 inches. Long range is up to 12 inches.
SensorNormalized is reading the NormalizedValue (aka SensorRaw) field from the Input module's IOMap structure. That's all. If you want to know what the firmware does then read the firmware source code. It is trivially easy to read if you can write random number generators or recursive maze solvers or a-star algorithms.
It has also been discussed somewhat thoroughly when we were talking about how the firmware provides access to the raw sensor values.
The unmodified raw value is provided like this:
Code: Select all
dInputGetRawAd(&InputVal, No);
IOMapInput.Inputs[No].ADRaw = InputVal;
It is available in NXC via SensorRaw(port), SensorValueRaw(port), or GetInput(port, RawValueField).
The normalized and scaled values are provided like this:
Code: Select all
if (sType == REFLECTION)
{
cInputCalcFullScale(&InputVal, REFLECTIONSENSORMIN, REFLECTIONSENSORPCTDYN, TRUE);
}
else if (sType == TEMPERATURE)
{
if (InputVal < 290)
InputVal = 290;
else if (InputVal > 928)
InputVal = 928;
InputVal = TempConvTable[(InputVal) - /*197*/ 290];
InputVal = InputVal + 200;
InputVal = (UWORD)(((SLONG)InputVal * (SLONG)1023)/(SLONG)900);
}
else if (sType == LIGHT_ACTIVE || sType == LIGHT_INACTIVE)
{
cInputCalcFullScale(&InputVal, NEWLIGHTSENSORMIN, NEWLIGHTSENSORPCTDYN, TRUE);
}
else if (sType == SOUND_DB || sType == SOUND_DBA)
{
cInputCalcFullScale(&InputVal, NEWSOUNDSENSORMIN, NEWSOUNDSENSORPCTDYN, TRUE);
}
else if (sType == CUSTOM)
{
cInputCalcFullScale(&InputVal, IOMapInput.Inputs[No].CustomZeroOffset, IOMapInput.Inputs[No].CustomPctFullScale, FALSE);
}
cInputCalcSensorValue( InputVal, // <-- this is the normalized raw value (input to this function and output from cInputCalcFullScale)
&(IOMapInput.Inputs[No].SensorRaw), // <-- this is the normalized raw value (always == InputVal)
&(IOMapInput.Inputs[No].SensorValue), // <-- this is the scaled value
&(IOMapInput.Inputs[No].SensorBoolean), // <-- this is the boolean value
&(VarsInput.InputDebounce[No]),
&(VarsInput.SampleCnt[No]),
&(VarsInput.LastAngle[No]),
&(VarsInput.EdgeCnt[No]),
((IOMapInput.Inputs[No].SensorMode) & SLOPEMASK),
((IOMapInput.Inputs[No].SensorMode) & MODEMASK));
and then this:
Code: Select all
void cInputCalcFullScale(UWORD *pRawVal, UWORD ZeroPointOffset, UBYTE PctFullScale, UBYTE InvStatus)
{
if (*pRawVal >= ZeroPointOffset)
{
*pRawVal -= ZeroPointOffset;
}
else
{
*pRawVal = 0;
}
*pRawVal = (*pRawVal * 100)/PctFullScale;
if (*pRawVal > SENSOR_RESOLUTION)
{
*pRawVal = SENSOR_RESOLUTION;
}
if (TRUE == InvStatus)
{
*pRawVal = SENSOR_RESOLUTION - *pRawVal;
}
}
and this:
Code: Select all
void cInputCalcSensorValue(UWORD NewSensorRaw, UWORD *pOldSensorRaw, SWORD *pSensorValue,
UBYTE *pBoolean, UBYTE *pDebounce, UBYTE *pSampleCnt,
UBYTE *LastAngle, UBYTE *pEdgeCnt, UBYTE Slope,
UBYTE Mode)
{
SWORD Delta;
UBYTE PresentBoolean;
UBYTE Sample;
if (0 == Slope)
{
/* This is absolute measure method */
if (NewSensorRaw > THRESHOLD_FALSE)
{
PresentBoolean = FALSE;
}
else
{
if (NewSensorRaw < THRESHOLD_TRUE)
{
PresentBoolean = TRUE;
}
}
}
else
{
/* This is dynamic measure method */
if (NewSensorRaw > (ACTUAL_AD_RES - Slope))
{
PresentBoolean = FALSE;
}
else
{
if (NewSensorRaw < Slope)
{
PresentBoolean = TRUE;
}
else
{
Delta = *pOldSensorRaw - NewSensorRaw;
if (Delta < 0)
{
if (-Delta > Slope)
{
PresentBoolean = FALSE;
}
}
else
{
if (Delta > Slope)
{
PresentBoolean = TRUE;
}
}
}
}
}
*pOldSensorRaw = NewSensorRaw;
switch(Mode)
{
case RAWMODE:
{
*pSensorValue = NewSensorRaw;
}
break;
case BOOLEANMODE:
{
*pSensorValue = PresentBoolean;
}
break;
case TRANSITIONCNTMODE:
{
if ((*pDebounce) > 0)
{
(*pDebounce)--;
}
else
{
if (*pBoolean != PresentBoolean)
{
(*pDebounce) = DEBOUNCERELOAD;
(*pSensorValue)++;
}
}
}
break;
case PERIODCOUNTERMODE:
{
if ((*pDebounce) > 0)
{
(*pDebounce)--;
}
else
{
if (*pBoolean != PresentBoolean)
{
(*pDebounce) = DEBOUNCERELOAD;
*pBoolean = PresentBoolean;
if (++(*pEdgeCnt) > 1)
{
if (PresentBoolean == 0)
{
(*pEdgeCnt) = 0;
(*pSensorValue)++;
}
}
}
}
}
break;
case PCTFULLSCALEMODE:
{
/* Output is 0-100 pct */
*pSensorValue = ((NewSensorRaw) * 100)/SENSOR_RESOLUTION;
}
break;
case FAHRENHEITMODE:
{
/* Fahrenheit mode goes from -40 to 158 degrees */
*pSensorValue = (((ULONG)(NewSensorRaw) * 900L)/SENSOR_RESOLUTION) - 200;
*pSensorValue = ((180L * (ULONG)(*pSensorValue))/100L) + 320;
}
break;
case CELSIUSMODE:
{
/* Celsius mode goes from -20 to 70 degrees */
*pSensorValue = (((ULONG)(NewSensorRaw * 900L)/SENSOR_RESOLUTION) - 200);
}
break;
case ANGLESTEPSMODE:
{
*pBoolean = PresentBoolean;
if (NewSensorRaw < ANGLELIMITA)
{
Sample = 0;
}
else
{
if (NewSensorRaw < ANGLELIMITB)
{
Sample = 1;
}
else
{
if (NewSensorRaw < ANGLELIMITC)
{
Sample = 2;
}
else
{
Sample = 3;
}
}
}
switch (*LastAngle)
{
case 0 :
{
if (Sample == 1)
{
if ((*pSampleCnt) >= ROT_SLOW_SPEED )
{
if (++(*pSampleCnt) >= (ROT_SLOW_SPEED + ROT_OV_SAMPLING))
{
(*pSensorValue)++;
(*LastAngle) = Sample;
}
}
else
{
(*pSensorValue)++;
(*LastAngle) = Sample;
}
}
if (Sample == 2)
{
(*pSensorValue)--;
(*LastAngle) = Sample;
}
if (Sample == 0)
{
if ((*pSampleCnt) < ROT_SLOW_SPEED)
{
(*pSampleCnt)++;
}
}
}
break;
case 1 :
{
if (Sample == 3)
{
(*pSensorValue)++;
(*LastAngle) = Sample;
}
if (Sample == 0)
{
(*pSensorValue)--;
(*LastAngle) = Sample;
}
(*pSampleCnt) = 0;
}
break;
case 2 :
{
if (Sample == 0)
{
(*pSensorValue)++;
(*LastAngle) = Sample;
}
if (Sample == 3)
{
(*pSensorValue)--;
(*LastAngle) = Sample;
}
(*pSampleCnt) = 0;
}
break;
case 3 :
{
if (Sample == 2)
{
if ((*pSampleCnt) >= ROT_SLOW_SPEED)
{
if (++(*pSampleCnt) >= (ROT_SLOW_SPEED + ROT_OV_SAMPLING))
{
(*pSensorValue)++;
(*LastAngle) = Sample;
}
}
else
{
(*pSensorValue)++;
(*LastAngle) = Sample;
}
}
if (Sample == 1)
{
(*pSensorValue)--;
(*LastAngle) = Sample;
}
if (Sample == 3)
{
if ((*pSampleCnt) < ROT_SLOW_SPEED)
{
(*pSampleCnt)++;
}
}
}
break;
}
}
}
*pBoolean = PresentBoolean;
}
The normalized value is available in NXC via SensorNormalized(port) or GetInput(port, NormalizedValueField).
The scaled value is available in NXC via Sensor(port), SENSOR_n, SensorValue(port), SensorScaled(port), or GetInput(port, ScaledValueField).
John Hansen