void init_dislin(Dislin& g) { g.metafl ("cons"); g.scrmod ("revers"); g.disini (); g.pagera (); g.complx (); g.axspos (450, 1800); g.axslen (2200, 1200); g.name ("X-axis", "x"); g.name ("Y-axis", "y"); g.labdig (-1, "x"); g.ticks (9, "x"); g.ticks (10, "y"); g.titlin ("Energy over generations", 1); g.titlin ("Energy", 3); int ic = g.intrgb (0.95,0.95,0.95); g.axsbgd (ic); //g.graf (0.0, 360.0, 0.0, 90.0, -1.0, 1.0, -1.0, 0.5); g.setrgb (0.7, 0.7, 0.7); g.grid (1, 1); g.color ("fore"); g.height (50); g.title (); }
int main( int argc, char *argv[], char *env[] ) { Verilated::commandArgs( argc, argv ); top = new Vbldc_mcasic_enc; top->clk = 0; top->eval(); Dislin g; g.itmstr( "Yes!", 1 ); g.metafl( "CONS" ); g.setpag( "da4l" ); // Page format static const double power_supply_voltage = 12.0; // [V] // TODO: Need to account for rounded off encoder counts in HDL. static const int rotor_pole_pair_cnt = 6; static const int enc_lpr = 334; // [lines/rev] top->period = ( enc_lpr << 2 ) / rotor_pole_pair_cnt; printf( "Electrical commutation period: %d eu\n", top->period ); static const double sqrt3 = sqrt( 3.0 ); static const double enc_res = 2.0 * M_PI / (double)( enc_lpr << 2 ); // [rad/eu] printf( "Encoder resolution: %.6f rad/eu.\n", enc_res ); static const double dt = 1 / 50E6; // [sec] static const double tmax = 0.2; // [sec] static const int step_max = tmax / dt + 1; printf( "Step max: %d\n", step_max ); static double A[step_max]; static double B[step_max]; // Keep these out of the stack by making them static. static double t[step_max]; // [sec] static double stator_phase[step_max]; static double rotor_phase[step_max]; static double mtr_phase[step_max]; static double mtr_vel[step_max]; static double winding_voltage[3][step_max]; top->clk = 0; top->pwm = 1024; top->A = 0; top->B = 0; top->eval(); typedef struct { int A; int B; } quad_state_t; static const quad_state_t quad_state_arr[] = { // A, B { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }, }; static const int quad_state_cnt = sizeof( quad_state_arr ) / sizeof( quad_state_arr[0] ); static int quad_state_idx = 0; static double enc_line_phase = 0.0; // [rad] Position of last quadrature state change. A[0] = quad_state_arr[quad_state_idx].A; B[0] = quad_state_arr[quad_state_idx].B; t[0] = 0.0; stator_phase[0] = 0.0; rotor_phase[0] = 0.0; mtr_phase[0] = 0.0; mtr_vel[0] = 0.0; // bldc_mcasic_enc( clk, rst, pwm, offset, period, A, B, out ); // First order digital low-pass butterworth filter with cut-off frequency of 100 Hz and sampling frequency of 50 MHz. static const double Abutter = 0.999987433708342; static const double Bbutter = 1.777142009174172E-05; static const double Cbutter = 0.707102338331525; static const double Dbutter = 6.283145829092713E-06; static int step_cnt; for ( step_cnt = 1; step_cnt < step_max; ++step_cnt ) { t[step_cnt] = t[step_cnt-1] + dt; // [sec] mtr_vel[step_cnt] = 10; // [rad/sec] mtr_phase[step_cnt] = mtr_phase[step_cnt-1] + mtr_vel[step_cnt-1] * dt; // [rad] stator_phase[step_cnt] = 0.0; rotor_phase[step_cnt] = 0.0; // Simulate encoder. if ( mtr_phase[step_cnt] >= enc_line_phase + enc_res ) { quad_state_idx = ( quad_state_idx + 1 ) % quad_state_cnt; enc_line_phase += enc_res; // Update the location of the last quadrature state change. } else if ( mtr_phase[step_cnt] <= enc_line_phase - enc_res ) { quad_state_idx = ( quad_state_idx - 1 ) % quad_state_cnt; enc_line_phase -= enc_res; // Update the location of the last quadrature state change. } if ( abs( mtr_phase[step_cnt] - enc_line_phase ) >= enc_res ) { printf( "Error: Multiple quadrature states in a single timestep." " Timestep: %.6f sec, velocity: %.3f rad/sec\n", dt, mtr_vel[step_cnt] ); break; } top->A = quad_state_arr[quad_state_idx].A; top->B = quad_state_arr[quad_state_idx].B; A[step_cnt] = top->A; B[step_cnt] = top->B; top->clk = 1; top->eval(); top->clk = 0; top->eval(); static double xpwm[3] = { 0.0, 0.0, 0.0 }; int i; for ( i = 0; i < 3; ++i ) { winding_voltage[i][step_cnt] = Cbutter * xpwm[i] + Dbutter * power_supply_voltage * top->out[i]; xpwm[i] = Abutter * xpwm[i] + Bbutter * power_supply_voltage * top->out[i]; } //printf( "xpwm[2]: %.6f, out[2]: %d\n", xpwm[2], top->out[2] ); } g.disini(); // Initializes DISLIN g.pagera(); g.hwfont(); //g.axspos( 450, 1800 ); //g.axslen( 2200, 1200); g.name( "Time (sec)", "x" ); g.name( "Phase (rad)", "y" ); g.labdig( -1, "x" ); g.ticks( 5, "xy" ); g.titlin( "BLDC MCASIC ENC", 1 ); //g.titlin ("SIN(X), COS(X)", 3); /* GRAF plots a two-dimensional axis system. The call is: CALL GRAF (XA, XE, XOR, XSTP, YA, YE, YOR, YSTP) level 1 or: void graf (float xa, float xe, float xor, float xstp, float ya, float ye, float yor, float ystp); XA, XE are the lower and upper limits of the X-axis. XOR, XSTP are the first X-axis label and the step between labels. YA, YE are the lower and upper limits of the Y-axis. YOR, YSTP are the first Y-axis label and the step between labels. */ //g.graf( -2.0 * M_PI, ( (double)period_cnt + 1.0 ) * 2.0 * M_PI, 0.0, 90.0, -150, 150, -150, 50 ); g.graf( 0.0, tmax, 0.0, 1.0, -10.0, 10.0, -10, 1.0 ); g.title(); g.color( "red" ); g.curve( t, stator_phase, step_max ); g.color( "green" ); g.curve( t, rotor_phase, step_max ); g.color( "blue" ); g.curve( t, mtr_phase, step_max ); g.color( "fore" ); //g.dash(); // Sets dashed line style. g.xaxgit(); // Plots the line y = 0. g.endgrf(); // Encoder window. g.opnwin(2); g.name( "Time (sec)", "x" ); g.name( "Encoder", "y" ); g.labdig( -1, "x" ); g.ticks( 5, "xy" ); g.graf( 0.0, tmax, 0.0, 1.0, -1.0, 2.0, -1.0, 0.5 ); g.title(); g.color( "red" ); g.curve( t, A, step_max ); g.color( "green" ); g.curve( t, B, step_max ); g.color( "fore" ); g.endgrf(); // Phase voltage window g.opnwin(3); g.name( "Time (sec)", "x" ); g.name( "Voltage (V)", "y" ); g.labdig( -1, "x" ); g.ticks( 5, "xy" ); g.graf( 0.0, tmax, 0.0, 1.0, -1.0, power_supply_voltage + 1.0, -1.0, 0.5 ); g.title(); g.color( "red" ); g.curve( t, winding_voltage[0], step_max ); g.color( "green" ); g.curve( t, winding_voltage[1], step_max ); g.color( "blue" ); g.curve( t, winding_voltage[2], step_max ); g.color( "fore" ); g.endgrf(); g.disfin(); // Terminates DISLIN delete top; exit( 0 ); }
int main( int argc, char *argv[], char *env[] ) { Verilated::commandArgs( argc, argv ); top = new Vsine3; top->clk = 0; top->eval(); Dislin g; g.itmstr( "Yes!", 1 ); g.metafl( "CONS" ); g.setpag( "da4l" ); top->period = 64; const int period_cnt = 2; // [periods] const int res = 100; // [samples/period] const int sample_cnt = period_cnt * res; // [samples] const double dx = 2.0 * M_PI / (double)res; double x[3][sample_cnt]; // [radians] double y[3][sample_cnt]; int n; for ( n = 0; n < sample_cnt; ++n ) { x[0][n] = (double)n * dx; // [radians] x[1][n] = x[0][n]; // [radians] x[2][n] = x[0][n]; // [radians] top->in0 = (int)round( x[0][n] * (double)top->period / 2.0 / M_PI ); top->in1 = (int)round( ( x[1][n] - 2.0 * M_PI / 3.0 ) * (double)top->period / 2.0 / M_PI ); top->in2 = (int)round( ( x[2][n] + 2.0 * M_PI / 3.0 ) * (double)top->period / 2.0 / M_PI ); top->eval(); y[0][n] = ( (double)(signed char)top->out0 ); y[1][n] = ( (double)(signed char)top->out1 ); y[2][n] = ( (double)(signed char)top->out2 ); //printf( "n: %d, in0: %d, out0: %d\n", // n, top->in0, (signed char)top->out0 ); } g.disini(); g.pagera(); g.hwfont(); g.axspos( 450, 1800 ); g.axslen( 2200, 1200) ; g.name( "Phase (radians)", "x" ); g.name( "Sine (8 bit)", "y" ); g.labdig( -1, "x" ); g.ticks( 10, "xy" ); g.titlin( "Sine simulation", 1 ); //g.titlin ("SIN(X), COS(X)", 3); g.graf( -2.0 * M_PI, ( (double)period_cnt + 1.0 ) * 2.0 * M_PI, 0.0, 90.0, -150, 150, -150, 50 ); g.title(); g.color( "red" ); g.curve( x[0], y[0], sample_cnt ); g.color( "green" ); g.curve( x[1], y[1], sample_cnt ); g.color( "blue" ); g.curve( x[2], y[2], sample_cnt ); g.color( "fore" ); g.dash(); g.xaxgit(); g.disfin(); delete top; exit( 0 ); }