Initial work on compression waves feature

Not all configuration options are working for this yet
This commit is contained in:
Josh Stewart 2024-04-24 17:32:47 +10:00
parent 5017d87562
commit a9d61fb01d
9 changed files with 194 additions and 38 deletions

View File

@ -66,12 +66,14 @@ input::-moz-focus-inner {
padding: 0;
}
/*
input, select, textarea {
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
}
*/
/* Colummn */

View File

@ -80,6 +80,30 @@
<input type="range" id="rpmSweepSpeed" min="200" max="4000" step="10" value="3000" onChange="setSweepRPM()" disabled>
</div>
</div>
<div class="row">
<div class="col-7">Enable compression: </div>
<div class="col-2">
<input type="checkbox" id="compressionEnable" onChange="toggleCompression()">
</div>
</div>
<div class="row">
<div class="col-7">Configuration: </div>
<div class="col-2">
<select id="compressionMode" onChange="setCompressionMode()" disabled>
<option value="1">2-cyl 4 stroke</option>
<option value="3">4-cyl 4 stroke</option>
<option value="4">6-cyl 4 stroke</option>
<option value="5">8-cyl 4 stroke</option>
</select>
</div>
</div>
<div class="row">
<div class="col-7">Compression RPM: </div>
<div class="col-2">
<input type="number" id="compressionRPM" min="20" max="1000" step="1" value="400" onChange="setCompressionRPM()" disabled>
</div>
</div>
<div>
<br />
<center><input type='button' value="Save Config" id="btnSave" onclick="saveData(true);" /><div id="saveCheck" class="icon fa-check fadeOut" style="visibility:hidden; display:inline-block;margin-left: 0.75em;"></div></center>

View File

@ -6,7 +6,7 @@ const ByteLengthParser = require('@serialport/parser-byte-length')
const {ipcRenderer} = require("electron")
var port = new serialport('/dev/tty-usbserial1', { autoOpen: false })
var CONFIG_SIZE = 13;
var CONFIG_SIZE = 15;
var onConnectIntervalConfig;
var onConnectIntervalWheels;
var isConnected=false;
@ -215,13 +215,16 @@ function requestConfig()
function receiveConfig(data)
{
console.log("Received config: " + data);
console.log("Mode: " + data[0]);
console.log("Mode: " + data[2]);
document.getElementById("rpmSelect").value = data[4];
document.getElementById("fixedRPM").value = (((data[6] & 0xff) << 8) | (data[5] & 0xff));
document.getElementById("rpmSweepMin").value = (((data[8] & 0xff) << 8) | (data[7] & 0xff));
document.getElementById("rpmSweepMax").value = (((data[10] & 0xff) << 8) | (data[9] & 0xff));
document.getElementById("rpmSweepSpeed").value = (((data[12] & 0xff) << 8) | (data[11] & 0xff));
document.getElementById("rpmSelect").value = data[2];
document.getElementById("fixedRPM").value = (((data[4] & 0xff) << 8) | (data[3] & 0xff));
document.getElementById("rpmSweepMin").value = (((data[6] & 0xff) << 8) | (data[5] & 0xff));
document.getElementById("rpmSweepMax").value = (((data[8] & 0xff) << 8) | (data[7] & 0xff));
document.getElementById("rpmSweepSpeed").value = (((data[10] & 0xff) << 8) | (data[9] & 0xff));
document.getElementById("compressionEnable").value = data[11];
document.getElementById("compressionMode").value = data[12];
document.getElementById("compressionRPM").value = (((data[14] & 0xff) << 8) | (data[13] & 0xff));
port.unpipe();
@ -623,6 +626,7 @@ window.onload = function ()
refreshSerialPorts();
redrawGears(toothPatterns[0]);
window.location.hash = '#connect';
//window.location.hash = '#live';
checkForUpdates();
//animateGauges();

View File

@ -29,6 +29,8 @@ void reset_new_OCR1A(uint32_t);
uint8_t get_bitshift_from_prescaler(uint8_t *);
void get_prescaler_bits(uint32_t *, uint8_t *, uint8_t *);
void setRPM(uint16_t);
uint16_t calculateCompressionModifier();
uint16_t calculateCurrentCrankAngle();
/* Prototypes */

View File

@ -29,6 +29,7 @@
#include <EEPROM.h>
struct configTable config;
struct status currentStatus;
/* Sensistive stuff used in ISR's */
volatile uint16_t adc0; /* POT RPM */
@ -39,12 +40,13 @@ volatile uint8_t analog_port = 0;
volatile bool adc0_read_complete = false;
volatile bool adc1_read_complete = false;
volatile bool reset_prescaler = false;
volatile bool normal = true;
volatile uint8_t output_invert_mask = 0x00; /* Don't invert anything */
volatile uint8_t prescaler_bits = 0;
volatile uint8_t last_prescaler_bits = 0;
volatile uint16_t new_OCR1A = 5000; /* sane default */
volatile uint16_t edge_counter = 0;
volatile uint32_t cycleStartTime = micros();
volatile uint32_t cycleDuration = 0;
uint32_t sweep_time_counter = 0;
uint8_t sweep_direction = ASCENDING;
@ -213,7 +215,7 @@ void setup() {
// Set ADSC in ADCSRA (0x7A) to start the ADC conversion
ADCSRA |= B01000000;
/* Make sure we are using the DEFAULT RPM on startup */
reset_new_OCR1A(config.rpm);
reset_new_OCR1A(currentStatus.rpm);
} // End setup
@ -252,22 +254,17 @@ ISR(ADC_vect){
/* Pumps the pattern out of flash to the port
* The rate at which this runs is dependent on what OCR1A is set to
*/
ISR(TIMER1_COMPA_vect) {
ISR(TIMER1_COMPA_vect)
{
/* This is VERY simple, just walk the array and wrap when we hit the limit */
PORTB = output_invert_mask ^ pgm_read_byte(&Wheels[config.wheel].edge_states_ptr[edge_counter]); /* Write it to the port */
/* Normal direction overflow handling */
if (normal)
edge_counter++;
if (edge_counter == Wheels[config.wheel].wheel_max_edges)
{
edge_counter++;
if (edge_counter == Wheels[config.wheel].wheel_max_edges) {
edge_counter = 0;
}
}
else
{
if (edge_counter == 0)
edge_counter = Wheels[config.wheel].wheel_max_edges;
edge_counter--;
edge_counter = 0;
cycleDuration = micros() - cycleStartTime;
cycleStartTime = micros();
}
/* The tables are in flash so we need pgm_read_byte() */
@ -301,18 +298,17 @@ void loop()
}
else if (config.mode == LINEAR_SWEPT_RPM)
{
//if(millis() > (sweep_time_counter + sweep_interval_ms))
if(micros() > (sweep_time_counter + config.sweep_interval))
{
sweep_time_counter = micros();
if(sweep_direction == ASCENDING)
{
tmp_rpm = config.rpm + 1;
tmp_rpm = currentStatus.rpm + 1;
if(tmp_rpm >= config.sweep_high_rpm) { sweep_direction = DESCENDING; }
}
else
{
tmp_rpm = config.rpm - 1;
tmp_rpm = currentStatus.rpm - 1;
if(tmp_rpm <= config.sweep_low_rpm) { sweep_direction = ASCENDING; }
}
}
@ -321,7 +317,55 @@ void loop()
{
tmp_rpm = config.fixed_rpm;
}
setRPM(tmp_rpm);
currentStatus.base_rpm = tmp_rpm;
currentStatus.compressionModifier = calculateCompressionModifier();
if(currentStatus.compressionModifier >= currentStatus.base_rpm ) { currentStatus.compressionModifier = 0; }
setRPM( (currentStatus.base_rpm - currentStatus.compressionModifier) );
}
uint16_t calculateCompressionModifier()
{
if( (currentStatus.rpm > config.compressionRPM) || (config.useCompression != true) ) { return 0; }
//if( currentStatus.base_rpm > 400 ) { return 0;}
uint16_t crankAngle = calculateCurrentCrankAngle();
uint16_t modAngle = crankAngle;
uint16_t compressionModifier = 0;
switch(config.compressionType)
{
case COMPRESSION_TYPE_2CYL_4STROKE:
modAngle = modAngle / 2;
compressionModifier = pgm_read_byte(&sin_100_180[modAngle]);
case COMPRESSION_TYPE_4CYL_4STROKE:
modAngle = (crankAngle % 180) ;
compressionModifier = pgm_read_byte(&sin_100_180[modAngle]);
break;
case COMPRESSION_TYPE_6CYL_4STROKE:
modAngle = crankAngle % 120;
compressionModifier = pgm_read_byte(&sin_100_120[modAngle]);
break;
case COMPRESSION_TYPE_8CYL_4STROKE:
modAngle = crankAngle % 90;
compressionModifier = pgm_read_byte(&sin_100_90[modAngle]);
break;
}
return compressionModifier;
}
uint16_t calculateCurrentCrankAngle()
{
if(cycleDuration == 0) { return 0; }
uint32_t cycleTime = micros() - cycleStartTime;
if( pgm_read_byte(&Wheels[config.wheel].wheel_degrees) == 720 ) { cycleTime = cycleTime / 2; }
uint16_t tmpCrankAngle = ((cycleTime * 360U) / cycleDuration);
while(tmpCrankAngle > 360) { tmpCrankAngle -= 360; }
return tmpCrankAngle;
}
/*!
@ -331,8 +375,8 @@ void setRPM(uint16_t newRPM)
{
if (newRPM < 10) { return; }
if(config.rpm != newRPM) { reset_new_OCR1A(newRPM); }
config.rpm = newRPM;
if(currentStatus.rpm != newRPM) { reset_new_OCR1A( newRPM ); }
currentStatus.rpm = newRPM;
}

View File

@ -132,7 +132,7 @@ void commandParser()
break;
case 'R': //Send the current RPM
Serial.println(config.rpm);
Serial.println(currentStatus.rpm);
break;
case 's': //Set the high and low RPM for sweep mode
@ -199,7 +199,7 @@ void toggle_invert_secondary_cb()
void display_new_wheel()
{
reset_new_OCR1A(config.rpm);
reset_new_OCR1A(currentStatus.rpm);
edge_counter = 0; // Reset to beginning of the wheel pattern */
}

View File

@ -28,18 +28,37 @@
#define TMP_RPM_CAP 9000 /* MAX RPM via pot control. Adjusted to 9,000rpm max from 16,384rpm to match the GUI */
#define EEPROM_LAST_MODE 100
struct configTable {
uint8_t version;
uint16_t rpm = 6000;
#define COMPRESSION_TYPE_1CYL_4STROKE 0 //Not initiallity supported
#define COMPRESSION_TYPE_2CYL_4STROKE 1
#define COMPRESSION_TYPE_3CYL_4STROKE 2 //Not initiallity supported
#define COMPRESSION_TYPE_4CYL_4STROKE 3
#define COMPRESSION_TYPE_6CYL_4STROKE 4
#define COMPRESSION_TYPE_8CYL_4STROKE 5
struct configTable
{
uint8_t version;
uint8_t wheel = FOUR_TWENTY_A;
uint8_t mode;
uint16_t fixed_rpm = 2500;
uint16_t sweep_low_rpm = 250;
uint16_t sweep_high_rpm = 4000;
uint16_t sweep_interval = 1000;
bool useCompression = false;
uint8_t compressionType = 0;
uint16_t compressionRPM = 400;
};
extern struct configTable config;
struct status
{
uint16_t base_rpm; //RPM excluding compression modifier
uint16_t compressionModifier;
uint16_t rpm; //Final RPM
};
extern struct status currentStatus;
/* Tie things wheel related into one nicer structure ... */
typedef struct _wheels wheels;
struct _wheels {
@ -51,4 +70,47 @@ struct _wheels {
const uint16_t wheel_degrees;
};
//A sin wave of amplitude 100 with a complete cycle in 180 degrees (1 entry per degree).
const uint8_t sin_100_180[] PROGMEM =
{
0,0,0,0,0,1,1,1,2,2,3,4,4,5,6,7,8,9,10,11,
12,13,14,15,17,18,19,21,22,24,25,27,28,30,
31,33,35,36,38,40,41,43,45,47,48,50,52,53,
55,57,59,60,62,64,65,67,69,70,72,73,75,76,
78,79,81,82,83,85,86,87,88,89,90,91,92,93,
94,95,96,96,97,98,98,99,99,99,100,100,100,
100,100,100,100,100,100,99,99,99,98,98,97,
96,96,95,94,93,92,91,90,89,88,87,86,85,83,
82,81,79,78,76,75,73,72,70,69,67,65,64,62,
60,59,57,55,53,52,50,48,47,45,43,41,40,38,
36,35,33,31,30,28,27,25,24,22,21,19,18,17,
15,14,13,12,11,10,9,8,7,6,5,4,4,3,2,2,1,1,
1,0,0,0,0
};
//A sin wave of amplitude 100 with a complete cycle in 90 degrees (1 entry per degree).
const uint8_t sin_100_90[] PROGMEM =
{
0,0,0,1,2,3,4,6,8,10,12,14,17,19,22,25,28,
31,35,38,41,45,48,52,55,59,62,65,69,72,75,
78,81,83,86,88,90,92,94,96,97,98,99,100,100,
100,100,100,99,98,97,96,94,92,90,88,86,83,81,
78,75,72,69,65,62,59,55,52,48,45,41,38,35,31,
28,25,22,19,17,14,12,10,8,6,4,3,2,1,0,0
};
//A sin wave of amplitude 100 with a complete cycle in 120 degrees
const uint8_t sin_100_120[] PROGMEM =
{
0,0,0,1,1,2,2,3,4,5,7,8,10,11,13,15,17,19,
21,23,25,27,30,32,35,37,40,42,45,47,50,53,
55,58,60,63,65,68,70,73,75,77,79,81,83,85,
87,89,90,92,93,95,96,97,98,98,99,99,100,100,
100,100,100,99,99,98,98,97,96,95,93,92,90,89,
87,85,83,81,79,77,75,73,70,68,65,63,60,58,55,
53,50,47,45,42,40,37,35,32,30,27,25,23,21,19,
17,15,13,11,10,8,7,5,4,3,2,2,1,1,0,0
};
#endif

View File

@ -9,6 +9,9 @@
#define EEPROM_SWEEP_RPM_MAX 8 //Note this is 2 bytes
#define EEPROM_SWEEP_RPM_INT 10 //Note this is 2 bytes
#define EEPROM_FIXED_RPM 12 //Note this is 2 bytes
#define EEPROM_USE_COMPRESSION 14
#define EEPROM_COMPRESSION_TYPE 15
#define EEPROM_COMPRESSION_RPM 16 //Note this is 2 bytes
void loadConfig();
void saveConfig();

View File

@ -11,7 +11,7 @@ void loadConfig()
{
//New arduino
config.wheel = 5; //36-1
config.rpm = 3000;
currentStatus.rpm = 3000;
config.mode = POT_RPM;
config.fixed_rpm = 3500;
@ -28,7 +28,7 @@ void loadConfig()
byte highByte = EEPROM.read(EEPROM_CURRENT_RPM);
byte lowByte = EEPROM.read(EEPROM_CURRENT_RPM+1);
config.rpm = word(highByte, lowByte);
currentStatus.rpm = word(highByte, lowByte);
highByte = EEPROM.read(EEPROM_FIXED_RPM);
lowByte = EEPROM.read(EEPROM_FIXED_RPM+1);
@ -52,10 +52,19 @@ void loadConfig()
if(config.sweep_low_rpm >= config.sweep_high_rpm) { config.sweep_low_rpm = config.sweep_high_rpm - 100; }
config.useCompression = EEPROM.read(EEPROM_USE_COMPRESSION);
config.compressionType = EEPROM.read(EEPROM_COMPRESSION_TYPE);
highByte = EEPROM.read(EEPROM_COMPRESSION_RPM);
lowByte = EEPROM.read(EEPROM_COMPRESSION_RPM+1);
config.compressionRPM = word(highByte, lowByte);
//config.compressionType = COMPRESSION_TYPE_6CYL_4STROKE;
//Error checking
if(config.wheel >= MAX_WHEELS) { config.wheel = 5; }
if(config.mode >= MAX_MODES) { config.mode = FIXED_RPM; }
if(config.rpm > 15000) { config.rpm = 4000; }
if(currentStatus.rpm > 15000) { currentStatus.rpm = 4000; }
if(config.compressionType > COMPRESSION_TYPE_8CYL_4STROKE) { config.compressionType = COMPRESSION_TYPE_4CYL_4STROKE; }
if(config.compressionRPM > 1000) { config.compressionRPM = 400; }
}
}
@ -65,8 +74,8 @@ void saveConfig()
EEPROM.update(EEPROM_RPM_MODE, config.mode);
EEPROM.update(EEPROM_VERSION, EEPROM_CURRENT_VERSION);
byte highByte = highByte(config.rpm);
byte lowByte = lowByte(config.rpm);
byte highByte = highByte(currentStatus.rpm);
byte lowByte = lowByte(currentStatus.rpm);
EEPROM.update(EEPROM_CURRENT_RPM, highByte);
EEPROM.update(EEPROM_CURRENT_RPM+1, lowByte);
@ -90,4 +99,10 @@ void saveConfig()
EEPROM.update(EEPROM_SWEEP_RPM_INT, highByte);
EEPROM.update(EEPROM_SWEEP_RPM_INT+1, lowByte);
EEPROM.update(EEPROM_USE_COMPRESSION, config.useCompression);
EEPROM.update(EEPROM_COMPRESSION_TYPE, config.compressionType);
highByte = highByte(config.compressionRPM);
lowByte = lowByte(config.compressionRPM);
EEPROM.update(EEPROM_COMPRESSION_RPM, highByte);
EEPROM.update(EEPROM_COMPRESSION_RPM+1, lowByte);
}