Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Klas-Kenny
Inlägg: 11292
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av Klas-Kenny »

Hur stor är din stack?
Shimonu
Inlägg: 294
Blev medlem: 21 oktober 2015, 22:44:33

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av Shimonu »

Stack är inte detsamma som RAM. Stacken ligger i RAM men den är inte lika stor som hela RAM:et
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av DanielM »

Klas-Kenny skrev: 20 juni 2021, 22:50:59 Hur stor är din stack?
Kan detta säga herrn något?
1.5 kb
Detta kanske förklarar varför en array på över 1500 bytes inte riktigt fungerade. :?
Skärmklipp.PNG
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
AndLi
Inlägg: 17050
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av AndLi »

Varför skickar du med hela arrayen och inte bara en pekare?
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av DanielM »

Men det är vad jag gör.
Array är ju pekare :)

Det ger samma krashande resultat när jag kör med detta.

Kod: Markera allt

test_func(uint8_t* plot)
Användarvisningsbild
AndLi
Inlägg: 17050
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av AndLi »

En array är en array
En pekare är en pekare
Rick81
Inlägg: 746
Blev medlem: 30 december 2005, 13:07:09

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av Rick81 »

Det beror ju på var du deklarerat den stora arrayen. Liggen den i en funktion (utan static) så hamnar den på stacken. Deklarar du den utanför funktion eller som static hamnar den i RAM.

Skickar du in uint8_t *data eller uint8_t data[] till funktion spelar ingen roll, det blir samma sak, det blir en pekare till arrayen.

Normalt sätt undviker man lägga så stora arrayer på stack i inbyggda system, men vill du ändå göra det, kan du utöka stackens storlek i .ld filen. Dock är det lite lurigt sätta korrekt storlek för det beror på i hur många steg funktioner med mycket arrayer anropas.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av DanielM »

Finns det inget sätt så jag kan få den ligga på FLASH? Då kanske jag måste ha den som const static? Men det vill jag inte ha.

Jag tror jag måste då offra lite av RAM. :) Ska testa ha en statisk uint8_t data[].

Edit:
Det fungerade inte.
Hmm...Jag får väll lösa detta på något annat sätt.
Senast redigerad av DanielM 21 juni 2021, 13:44:56, redigerad totalt 1 gång.
Rick81
Inlägg: 746
Blev medlem: 30 december 2005, 13:07:09

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av Rick81 »

Har du många fasta värden som tex en tabell för sinus eller nåt sånt liknande bör man lägga den i flash med const, men då kan du ju inte ändra den under körning.

Ett bra sätt lösa problemet är att man har en generisk data array som alla som inkluderar den headar filen kan accessa. Då kan du åter använda samma data buffer för olika funktioner. I ena fallet kan man vill göra en lång urskrift, nästa skicka ett UDP meddelande, ta emot en fet mängd data från SPI osv.... då kan man reservera så man har en ex 2 KB buffer som funktionerna få dela på. Skulle varje funktion har en static array skulle det då behöva 8 kB istället som exempel.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av DanielM »

Det är exakt detta jag gjorde, men det fungerade inte att skapa en stor array till att börja med.
Arrayen ska symbolisera en 2D array. Men det blir ju samma minne där med också.

Om du undrar hur koden ser ut så ser den ut så här.
Jag gör alltså en plot från en array.

Jag vet att jag kan använda memmove och jag ska göra det senare!

Kod: Markera allt

/*
 * new_values_measurement[row] Data array for inserting new values in data array for text
 * new_values_plot[row] Data array for inserting new values in data array for plot
 * labels[row][10] Char 2D array for displaying text labels
 * 1 <= row <= 6
 */
void LCD_Show_Plot_Frame(float new_values_measurement[], uint8_t new_values_plot[], char labels[][10], uint8_t row, bool run_in_background, bool clear_plot) {

	// Set rotation
	ILI9341_setRotation(2);

	static uint8_t plot[6*264]; // The reason why I placed it here is because stack memory is to low.
	static bool firstTimeRunning = true;

	// If we want to clear the plot for some reason
	if(clear_plot == true || firstTimeRunning){
		memset(plot, 0, 6*264); // 264 pixels from x0 to x1 for the plot. Don't change this.
		firstTimeRunning = false;
	}

	// If we running the the plot behind the "scene"
	if (run_in_background){
		for (int16_t i = 51; i < 315; i++)
			move(i, plot, new_values_plot, row);
		return;
	}

	// Update the text
	uint16_t colors[6] = {(uint16_t) COLOR_RED, (uint16_t) COLOR_CYAN, (uint16_t) COLOR_ORANGE, (uint16_t) COLOR_MAGENTA, (uint16_t) COLOR_GREEN3, (uint16_t) COLOR_MAROON};
	uint8_t x[6] = {55, 145, 235, 55, 145, 235};
	uint8_t y[6] = {10, 10, 10, 20, 20, 20};
	char text_value[10];
	char label[20];
	for(uint8_t i = 0; i < row; i++) {
		sprintf_(text_value, "%0.2f", new_values_measurement[i]);
		memcpy(label, labels[i], sizeof(labels[i]));
		strcat(label, text_value);
		ILI9341_printText(label, x[i], y[i], colors[i], COLOR_NAVY, 1);
	}

	// Change
	for (int16_t i = 51; i < 315; i++) {
		// Clear
		for(uint8_t j = 0; j < row; j++)
			ILI9341_DrawPixel(i, -plot[j*264 + i - 51] + 234, COLOR_NAVY);

		// Move
		move(i, plot, new_values_plot, row);

		// Fill
		for(uint8_t j = 0; j < row; j++)
			ILI9341_DrawPixel(i, -plot[j*264 + i - 51] + 234, colors[j]);
	}
}

static void move(uint16_t i, uint8_t plot[], uint8_t new_values_plot[], uint8_t row) {
	if (i < 314) {
		// We can only move values that have a next element
		for(uint8_t j = 0; j < row; j++)
			plot[j*264 + i - 51] = plot[j*264 + i - 50];
	} else {
		// Limits so we don't write outside the box
		for(uint8_t j = 0; j < row; j++)
			if (new_values_plot[j] < 203)
				plot[j*264 + i - 51] = new_values_plot[j];
			else
				plot[j*264 + i - 51] = 203;
	}
}
Användarvisningsbild
Klas-Kenny
Inlägg: 11292
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av Klas-Kenny »

Rick81 skrev: 21 juni 2021, 13:40:29 Ett bra sätt lösa problemet är att man har en generisk data array som alla som inkluderar den headar filen kan accessa. Då kan du åter använda samma data buffer för olika funktioner.
Detta blir ju i princip en "manuell" heap, då kan man ju egentligen bara göra heap större och använda malloc istället :D
Rick81
Inlägg: 746
Blev medlem: 30 december 2005, 13:07:09

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av Rick81 »

Detta blir ju i princip en "manuell" heap, då kan man ju egentligen bara göra heap större och använda malloc istället :D
Nja du kan inte fragmentera den på samma sätt på heap, vilket man vill undvika i inbyggda system så malloc ex. kan ge fel efter 1000 timmars körning om man fragmenterat den. Det är fortfarande statiskt minne (under förusättning att man inte fragmenterar det själv då)
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av DanielM »

Rick81 skrev: 21 juni 2021, 09:16:57 Normalt sätt undviker man lägga så stora arrayer på stack i inbyggda system, men vill du ändå göra det, kan du utöka stackens storlek i .ld filen. Dock är det lite lurigt sätta korrekt storlek för det beror på i hur många steg funktioner med mycket arrayer anropas.
Att utöka stacken tror jag ska låta bli. Jag har ingen erfarenhet om detta.
Jag har testat lagt den på RAM .bss och plot är 1.55 kB.

Edit:

Nu vet jag vad som också orsakar, trots att plot är statisk.

Denna orsakar också! Jag försöker alltså att rensa plot först.

Kod: Markera allt

memset(plot, 0, sizeof(plot));
Detta fungerar dock.

Kod: Markera allt

for(uint16_t i = 0; i < sizeof(plot); i++)
	plot[i] = 0;
Inte ens detta fungerar om plot är en 2D array [6][264]

Kod: Markera allt

for(uint8_t i = 0; i < 6; i++)
	memset(plot[i], 0, sizeof(plot[i]));
Jag ger upp. Det är inte meningen att jag ska använda stora arrayer på denna STM32.
Rick81
Inlägg: 746
Blev medlem: 30 december 2005, 13:07:09

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av Rick81 »

Testa om detta funkar:

Kod: Markera allt

uint8_t plot[6][264];
int main()
{
	memset(plot, 0, sizeof(plot));
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?

Inlägg av DanielM »

Alltså i main fungerar allt. Det är bara när funktionen är i en annan .c fil.
Men jag tror jag ska undvika skapa stora arrayer.

Målet var att skriva ut en plot på min LCD igenom att flytta pixlar. Det fungerar bra om det går långsamt, sämre om det går snabbt.

Men jag har bestämt mig att bara skriva ut värderna som min STM32 visar.
Det går riktigt bra nu :) Jag har fått SDADC, signel och differentiell att fungera. Dock så visar dom rätt höga värden, men jag tror detta har med att dom är förskjutna.

Målet med allt är att det ska vara en liten STM32 PLC som kan logga, styra och mäta :) Fri källkod också.

Exempel:
Vid singel SDADC så får jag 33490 om jag har 0 volt in. Annars blir det 12453 om jag applicerar 3.3v på ingången. Ungefär.
Vid differentiell SDADC så får jag 65509 om jag har 0 volt i skillnad. Applicerar jag 3.3 volt på någon av ingången så får jag ca 32523.

Jag har för mig att när jag konverterade om dessa uint16_t värden till int16 i Java, så fick jag 0 till 16-bit helt perfekt.

Edit:

En fråga! Är detta ett smart val?
Låt oss säga att jag har en encoder som har räkningen mellan 0x00 till 0xFFFF.
Men jag vill även bestämma åt vilket håll encodern roterar. Är det smart då och säga att encodern har räkningen mellan 0x00 till 0x7fff där sista biten är antingen en 1 eller 0 beroende på rotation?
0x7fff är alltså 15-bit.

Låt säga att 1 är för rotation medsols.
Då får jag värden mellan 32768 och 65535.
Om den roterar motsols så får jag värden mellan 0 till 32767.

Typ så här.

Kod: Markera allt

static uint16_t encoder0_difference;
static uint16_t encoder1_difference;
static TIM_HandleTypeDef* encoder0_tim;
static TIM_HandleTypeDef* encoder1_tim;

uint16_t compare(uint16_t count, uint16_t difference);

void STM32_PLC_Start_Encoder(TIM_HandleTypeDef* htim4, TIM_HandleTypeDef* htim19) {
	HAL_TIM_Encoder_Start_IT(htim4, TIM_CHANNEL_1);
	HAL_TIM_Encoder_Start_IT(htim4, TIM_CHANNEL_2);
	HAL_TIM_Encoder_Start_IT(htim19, TIM_CHANNEL_1);
	HAL_TIM_Encoder_Start_IT(htim19, TIM_CHANNEL_2);
	encoder0_tim = htim4;
	encoder1_tim = htim19;
}

uint16_t STM32_PLC_Encoder0() {
	uint16_t encoder0_count = encoder0_tim->Instance->CNT;
	encoder0_difference = compare(encoder0_count, encoder0_difference);
	bool encoder0_direction = !(__HAL_TIM_IS_TIM_COUNTING_DOWN(encoder0_tim));

	/* Values between 0 and 0xFFFF */
	if(encoder0_direction)
		return 0x8000 + encoder0_difference; /* Positive rotation: 0x8000 - 0xFFFF */
	else
		return 0x7FFF - encoder0_difference; /* Negative rotation: 0 - 0x7FFF */

}

uint16_t STM32_PLC_Encoder1() {
	uint16_t encoder1_count = encoder1_tim->Instance->CNT;
	encoder1_difference = compare(encoder1_count, encoder1_difference);
	bool encoder1_direction = !(__HAL_TIM_IS_TIM_COUNTING_DOWN(encoder1_tim));

	/* Values between 0 and 0xFFFF */
	if(encoder1_direction)
		return 0x8000 + encoder1_difference; /* Positive rotation: 0x8000 - 0xFFFF */
	else
		return 0x7FFF - encoder1_difference; /* Negative rotation: 0 - 0x7FFF */
}

void STM32_PLC_Encoder0_Set_Prescaler(uint16_t prescaler) {
	encoder0_tim->Instance->PSC = prescaler;
}

void STM32_PLC_Encoder1_Set_Prescaler(uint16_t prescaler) {
	encoder1_tim->Instance->PSC = prescaler;
}

uint16_t STM32_PLC_Encoder_Get(uint8_t i) {
	switch(i){
	case 0:
		return STM32_PLC_Encoder0();
	case 1:
		return STM32_PLC_Encoder1();
	default:
		return 0x7FFF; /* No rotation */
	}
}

uint16_t compare(uint16_t count, uint16_t difference) {
	if(count > difference)
		return count - difference;
	else if (count < difference)
		return difference - count;
	else
		return 0;
}
Skriv svar