Would you please share the schematic and firmware to public
@nikos44317
Ай бұрын
Yes, I have no objection, but I never drew a full schematic since this was a prototype in constant development. Nevertheless, there is a playlist named “Fluxgate magnetometer” that includes six videos with all the necessary information and schematics in a module-by-module basis. I will provide here the links, plus some comments plus the source code for the AVRs where it is applicable: Video no 1 “The sensor block of my fluxgate magnetometer” (link kzitem.info/news/bejne/1WmEsH5jbWZoZqw ) There is no need for a schematic, but the stl files of the 3D printed PLA parts may be available. Video no 2 “The power drive of my fluxgate magnetometer” (link kzitem.info/news/bejne/lZid33l6bZN8a6g ) The schematic of the module with comments starts at 0:31. There is no CPU. Video No 3 “The band pass filter of my fluxgate magnetometer” (link kzitem.info/news/bejne/u4htrXuQrJ6aoYo ) The schematic of the module with comments starts at 0:30. There is no CPU. Video No 4 “The synchronous detector of my fluxgate magnetometer” (link kzitem.info/news/bejne/0Gim22qfp1-bZmU ) The schematic of the detector with comments starts at 0:00. The time base is an ATmega 163 CPU and the logic description of the firmware starts at 1:02. The C code is: #include #include #include #include #define LOW_DETECT 0x00 #define HIGH_DETECT 0x04 #define LOW_DRIVE 0x01 #define HIGH_DRIVE 0x02 uint8_t table[256]; int main () { uint8_t poi; uint8_t offset; uint8_t i; DDRA = 0x00; // in PORTA = 0x7e; // pull up except first and last DDRB = 0x07; // out for last 3 bits DDRC = 0x00; // in DDRD = 0x00; // in poi = 0; for (i = 0; i < 64; i++) { table[poi] = LOW_DETECT; poi++; } for (i = 0; i < 64; i++) { table[poi] = HIGH_DETECT; poi++; } for (i = 0; i < 64; i++) { table[poi] = LOW_DETECT; poi++; } for (i = 0; i < 64; i++) { table[poi] = HIGH_DETECT; poi++; } offset = PINA; poi = offset; for (i = 0; i < 128; i++) { table[poi] |= LOW_DRIVE; poi++; } for (i = 0; i < 128; i++) { table[poi] |= HIGH_DRIVE; poi++; } poi = 0; while (1) // for ever { asm ("nop"); asm ("nop"); asm ("nop"); asm ("nop"); asm ("nop"); PORTB = table[poi]; poi++; } return 0; } Video No 5 “The integrator and voltage to current converter of my fluxgate magnetometer” (link kzitem.info/news/bejne/xYOqx4GApoyeaYI ) The schematic of the module starts at 0:00. There is no CPU. Video no 6 “The ADC and Display of my fluxgate magnetometer” (link kzitem.info/news/bejne/2aV9umurgpx-hno ) The schematic of the ADC is trivial. It is driven by an ATmega162 CPU and the logic description of its firmware starts at 0:00. The C code is: // Control ADS1213 by a ATmega162 // Clock of AVR = 4 MHz // SPI Master used to control thw ADC // AVR reports the readings of the 4 channels to RS232 at 19,200 baud #include #include #include #include #include #include #include #include #include #define F_CPU 4000000UL // for delays #include #define BAUDRATE 19200 #include "uart.h" // for delays in SPI and ADS #define TXIN 1.01 // 1us + 1% // prototypes void init (void); // all initialization tasks void ResetADS (void); // In slave ADS void write (uint8_t, uint8_t, uint8_t *); // write to ADS. address, count, bytes unsigned long read (uint8_t, uint8_t); // read from ADS address, count; long read_signed (void); // read 24 bits void channel(uint8_t); // select channel /* Macro */ #define set_bit(port, bit) (port |= (1
@nikos44317
Ай бұрын
Part two The schematic of the display is trivial. It is driven by another ATmega163 and the logic description of the firmware starts at 0:50. The C code is: // just accepting UART from sensor AVR and displaying the result - interrupts on RX // ATmega163L #include #include #include #include #include #include #include #include // for averaging #define MAXBUF 32 // for status #define BEFORE_START 0 #define CHECK_ONE 1 #define CHECK_SPACE 2 #define RECEIVE_VALUE 3 #define WAIT_CHANNEL 4 // for showing status #define B_S 1 #define C_O 2 #define C_S 4 #define R_V 8 #define W_C 16 #define MAIN 32 // control signals #define Eedge_low PORTB &= ~0x01 #define Eedge_high PORTB |= 0x01 #define RS_low PORTB &= ~0x08 #define RS_high PORTB |= 0x08 #define RW_low PORTB &= ~0x04 #define RW_high PORTB |= 0x04 // prototypes void init (); // initialization void display_show (uint8_t, uint8_t, char *); // write to screen pos, line, buffer void display_goto (uint8_t, uint8_t); // set cursor pos, line void display_command (uint8_t); // send a command to the display void display_wait (void); // wait until display not busy void delay (void); // small delay void display_write (uint8_t); // send data to the display void right_buf (uint8_t); // right adjust display buffer to length static uint8_t status; // reading engine status static int8_t channel; // channel number 1=0 static uint8_t poi; // pointer to buffers static uint8_t cpoi; // pointer in char buffer static int8_t sign; // temporary of sign static char rbuf[13], nbuf[13], dbuf[13]; // receive, number and display buffer static int32_t temp, val[3][MAXBUF]; // temporary channel value, 3 channel queue static int32_t sumval[3]; // 3 sums static double corrected; // one component after calculations volatile static int16_t aux; // just for delay // strings for display const char line0[] PROGMEM = " Magnetometer"; const char line1[] PROGMEM = "Bx = nT"; const char line2[] PROGMEM = "By = nT"; const char line3[] PROGMEM = "Bz = nT"; void right_buf (uint8_t size) // right adjust display buffer to length { uint8_t len, i; len = strlen (nbuf); for (i = 0; i < (size - len); i++) dbuf[i] = ' '; for (i = 0; i 3) line = 3; if (pos > 19) pos = 19; if (line == 0) address = pos; if (line == 1) address = pos + 64; if (line == 2) address = pos + 20; if (line == 3) address = pos + 84; address = address + 0x80; /* address = 1_______ */ display_command (address); } void display_show (uint8_t pos, uint8_t line, char * word) // write to screen { display_goto (pos, line); while (* word != 0) { display_write (* word); word++; } } void init (void) // initialization tasks { uint8_t i; char buf[21]; // prepare the ports DDRA = 0x00; // port A is for I/O LCD data PORTA = 0x00; // DDRB = 0x0D; // Port B is for output LCD control PORTB = 0x00; // DDRC = 0x7F; // Port C is for showing status PORTC = 0x00; // No pull ups in portC DDRD = 0x00; // Port D is only UART PORTD = 0x00; // no pull_up PORTD // set up UART UCSRA = 0x00; // normal speed UCSRB = 0x98; // enable Receive interrupt, R + T UBRRHI = 0x00; // 19200 baud MSB UBRR = 0x0C; // 19200 baud LSB // set up the display Eedge_low; display_command (0x38); /* Function set */ display_command (0x0C); /* Display on and cursor off */ display_command (0x06); /* Entry mode set */ display_command (0x01); /* Clear and set DD RAM 00 */ strcpy_P (buf, line0); // initialization of display display_show (0, 0, buf); strcpy_P (buf, line1); display_show (0, 1, buf); strcpy_P (buf, line2); display_show (0, 2, buf); strcpy_P (buf, line3); display_show (0, 3, buf); // zero buffers for (i = 0; i < MAXBUF; i++) { val[0][i] = 0; val[1][i] = 0; val[2][i] = 0; } // zero sums sumval[0] = 0; sumval[1] = 0; sumval[2] = 0; poi = 0; cpoi = 0; sign = 1; status = BEFORE_START; sei (); return; } ISR (UART_RX_vect) // when receiving a character { uint8_t c, i; c = UDR; switch (status) { case BEFORE_START: // wait for channel 1 == X PORTC = B_S; if (c == ' ') status = CHECK_ONE; break; case CHECK_ONE: PORTC = C_O; if (c == '1') { channel = 0; status = CHECK_SPACE; } else status = BEFORE_START; break; case CHECK_SPACE: PORTC = C_S; if (c == ' ') { cpoi = 0; status = RECEIVE_VALUE; } else status = BEFORE_START; break; case RECEIVE_VALUE: PORTC = R_V; if (c != ' ') { rbuf[cpoi] = c; cpoi++; } else { if (channel == 3) { // calculate Bx corrected = (0.42 * sumval[0] - 0.0078 * sumval[1] + 0.00675 * sumval[2]) / (double) MAXBUF; temp = (int32_t) corrected; ltoa (temp, nbuf, 10); right_buf (12); display_show (5, 1, dbuf); // calculate By corrected = (0.429 * sumval[1] - 0.00919 * sumval[0] - 0.04932 * sumval[2]) / (double) MAXBUF; temp = (int32_t) corrected; ltoa (temp, nbuf, 10); right_buf (12); display_show (5, 2, dbuf); // calculate Bz corrected = (0.4011 * sumval[2] + 0.00858 * sumval[0] - 0.04792 * sumval[1]) / (double) MAXBUF; temp = (int32_t) corrected; ltoa (temp, nbuf, 10); right_buf (12); display_show (5, 3, dbuf); poi++; if (poi >= MAXBUF) poi = 0; } else { sign = 1; temp = 0; for (i = 0; i < cpoi - 1; i++) // ignore the last character which is { if (rbuf[i] == '-') sign = -1; else temp = temp * 10 + rbuf[i] - '0'; } if (sign == -1) temp = - temp; sumval[channel] -= val[channel][poi]; val[channel][poi] = temp; sumval[channel] += temp; } status = WAIT_CHANNEL; } break; case WAIT_CHANNEL: PORTC = W_C; channel = c - '1'; status = CHECK_SPACE; break; default: break; } } int main (void) { init (); while (1) // for ever show status MAIN { PORTC = MAIN; } return 0; } The Power supply schematic is trivial and the description of the outputs starts at 1:32. There is no CPU. I wish you success with your projects. Nikos
Пікірлер: 3