Målet er å lage ett gaussmeter basert på en hall effekt sensor. Verdien skal vises på en LCD skjerm.

Utstyr

  • STM32F303K8 (Mikrokontroller)
  • SS495A (Hall effekt sensor)
  • EA DOGM164 (Skjerm)
  • EA LED40x33-A (Bakgrunnsbelysning)
  • 2 stk. 1uF kondensator
  • 2 stk. 1,2K ohm motstand
  • 20 ohm motstand
20190302_180055

STM32F303K8 mikrokontroller

Oppsett

gaussmeter_oppsett

Forklaring hall effekt sensor

Vi kjører 5V spenning over hall effekt sensoren. Utgangen på denne vil bli 2.5V så lenge målt gauss er 0. Siden dette betyr at spenningen ut kan bli over 3.3V som er maks spenning inn på mikrokontrolleren så deler vi denne i to før vi måler den analoge verdien på mikrokontrolleren.

For hver 3.125mV endring så er den målte verdien +/- 1 gauss. Siden den blir delt på to så vil 1 gauss endring på inngangen til mikrokontrolleren være 1.562mV.

495A

SS495A hall effekt sensor.

Forklaring oppsett skjerm

Skjermen er koblet til mikrokontrolleren med SPI. SPI modusen til skjermen må være modus 3. Det vil si at den trigger på endring fra lav til høy og at polariteten er høy. Maks frekvens er 400Khz, men er i dette tilfellet satt til ca. 32Khz.

20190302_180116

EADOGS164-A LCD skjerm. På undersiden kan du såvidt se bakgrunnsbelysningsmodulen.

Forklaring oppsett bakgrunnsbelysning

Bakgrunnsbelysningen er koblet i paralell med en 20 ohms i serie med bakgrunnsbelysningen. Motstanden er for å regulere strømmen. Verdien av denne er satt basert på informasjon i den tekniske beskrivelsen av bakgrunnsbelysningen.

 

Gauss verdi

ADC verdi Spenning Gauss
222 0.179 -640 Gauss
300 0.2415 -600 Gauss
494 0.39775 -500 Gauss
688 0.554 -400 Gauss
882 0.71025 -300 Gauss
1076 0.8665 -200 Gauss
1269 1.02275 -100 Gauss
1463 1.179 0 Gauss
1657 1.33525 100 Gauss
1851 1.4915 200 Gauss
2045 1.64775 300 Gauss
2239 1.804 400 Gauss
2433 1.96025 500 Gauss
2627 2.1165 600 Gauss
2705 2.179 640 Gauss

Dette er omtrent verdier beregnet siden jeg ikke har noe å teste verdiene mot.

Bilder

20190302_203817

20190302_203757

20190302_203749

Kode

Koden for å initalisere analog til digital konvertering. Den er konfigurert til 12bit og kjører en ekstra kalibrering på slutten.

ADC_MultiModeTypeDef multimode = { 0 };
ADC_ChannelConfTypeDef sConfig = { 0 };

hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
if (HAL_ADC_Init(&hadc1) != HAL_OK) {
  Error_Handler();
}

multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK) {
  Error_Handler();
}

sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
  Error_Handler();
}
while(HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK);

 

Her konfigureres oppkoblingen til skjermen. Det viktige her at den må være 8bit, polariteten må være høy og fasen til andre kant.

hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_1LINE;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
hspi1.Init.FirstBit = SPI_FIRSTBIT_LSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK) {
  Error_Handler();
}

 

Her konfigureres SPI koblingen for SCLK, MOSI og MISO.

GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 

Her konfigureres pin 11 som resett på skjermen.

GPIO_InitStruct.Pin = GPIO_PIN_11; //Konfigurer Pin 11
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Utgang push-pull.
GPIO_InitStruct.Pull = GPIO_PULLDOWN; // Utgang trekt ned.
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; //Høy hastighet på utgang
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 

Skjermen initaliseres.

void InitDisplay(void) {
  HAL_Delay(500);
  ResetDisplay();
  HAL_Delay(20);
  TransmitSpi(RS_INS, 0x08); //Slå av skjermen, hvis på.
  TransmitSpi(RS_INS, 0x3A); //Slå på skjermen. 
  TransmitSpi(RS_INS, 0x09); //Utvidet funksjonskall. 5 piksel font, 
                           //BW invertering slått av,
                           //4 linje skjerm slått på.
  TransmitSpi(RS_INS, 0x06); //Topp/Bunn satt til bunn.
  TransmitSpi(RS_INS, 0x1E); //Setter BIAS
  TransmitSpi(RS_INS, 0x39); //Funksjon satt.
  TransmitSpi(RS_INS, 0x1B); //Setter den interne oscillering til bias=1/6.
  TransmitSpi(RS_INS, 0x6C); //Setter intern motstand for spenningsdeling.
  TransmitSpi(RS_INS, 0x54); //Booster på og setter de to høyeste 
                           //bitene av konstrasten.
  TransmitSpi(RS_INS, 0x70); //Setter de fire siste bitene av konstrasten.
  TransmitSpi(RS_INS, 0x38); //Setter funksjon.
  TransmitSpi(RS_INS, 0x0C); //Skjerm på.
}

 

Sender data over spi til skjermdriveren. RS parameteren foreller om det er data som skal vises på skjermen eller om det er en instruksjon. Hvert kall består av tre byte.

Den første består av 5 byte som er høy som brukes til synkronisering, deretter les/skriv bit, deretter en bit som forteller om det er instruksjon eller data og til slutt en lav bit.

Hver data sendes en byte som sendes i to byte.

Skal sendes: 11001010
Byte 1 (4 første bit) Byte 1 (4 siste bit) 2 byte (4 siste bit) 2 byte (4 siste bit)
0101 0000 0011 0000
void TransmitSpi(uint8_t rs, uint8_t data) {
  HAL_Delay(5);
  uint8_t msb = (data & 0xF0) >> 4;
  uint8_t lsb = (data & 0x0F);
  uint8_t cmd[SPI_COMMAND_SIZE] = { 0x1F | rs, lsb, msb };
  HAL_SPI_Transmit(&hspi1, cmd, SPI_COMMAND_SIZE, 100);
  HAL_Delay(5);
}

 

Posisjon som skal skrives til er for 4 linjers skjerm satt til 0x80 på linje 1, 0x80+0x20 for linje 2, 0x80+0x40 for linje 3.

void SetCursor(uint8_t y, uint8_t x) {
  TransmitSpi(RS_INS, (uint8_t)0x80 + (0x20*y) + x);
}

 

Sletter all informasjon på skjermen.

void ClearScreen() {
  TransmitSpi(RS_INS, 0x01);
}

 

Skriver ut en karakter til skjermen om gangen. For hvert kall så flyttes markøren i minnet en plass så vi trenger ikke sette markøren for hvert kall.

void PrintString(char* str, int len) {
  for (int i = 0;i < len;i++) {
    TransmitSpi(RS_DATA, str[i]);
  }
}

 

Prosjekt koden kan finnes her.

 

 

 

Sendt av Kjetil Fjellheim