Respan Dataset Explorer

Select one behavior. Every returned turn has one binary label: Present or Absent. Source: final dense boolean release.

5,167,182physical rows
86shards
0.00%qualified row coverage
0.00%qualified cell coverage
Random row JSON API

turns-00052.parquet:48542

3141259c14fbfa2390a1f704
turn 3/5gpt-4o-2024-08-06PersianIran27 words
degenerate_repetitionAbsentFinal dense release
USER
معادل فارسی واژه کتاب
ASSISTANT
معادل فارسی واژه "کتاب" همان "کتاب" است، زیرا خود این واژه ریشه در زبان فارسی دارد و معادل دیگری در این زبان ندارد.

turns-00052.parquet:48543

7b9da3ea91223cb2f45055c5
turn 4/5gpt-4o-2024-08-06PersianIran14 words
degenerate_repetitionAbsentFinal dense release
USER
معادل فارسی واژه مستقل
ASSISTANT
واژه "مستقل" در فارسی به معنای "خودمختار" یا "آزاد" است.

turns-00052.parquet:48544

cecc3990336ef7a8d01cff90
turn 5/5gpt-4o-2024-08-06PersianIran15 words
degenerate_repetitionAbsentFinal dense release
USER
معادل فارسی واژه مستقلا
ASSISTANT
معادل فارسی واژه "مستقلاً" می‌تواند "به‌طور مستقل" یا "به‌صورت مستقل" باشد.

turns-00052.parquet:48545

3e5487e0cd1ea89e2f1a499d
turn 1/1o1-mini-2024-09-12EnglishCanada6794 words
degenerate_repetitionAbsentFinal dense release
USER
/*
 * File:   ADC.c
 * Author: younn
 *
 * Created on October 30, 2024, 1:16 PM
 */

#include "xc.h"
#include "ADC.h"

void ADC_init(void) {
    AD1PCFGbits.PCFG5 = 0;
    AD1CON1 = 0x0000;
    AD1CON1bits.FORM = 0b00;
    AD1CON1bits.SSRC = 0b111;
    AD1CON1bits.ASAM = 0;
    AD1CON2 = 0x0000;
    AD1CON3 = 0x0000;
    AD1CON3bits.ADRC = 0;
    AD1CON3bits.SAMC = 31;
    AD1CON3bits.ADCS = 2;
    AD1CHS = 0x0005;
    AD1CSSL = 0x0000;
}

uint16_t do_ADC(void) {
    AD1CON1bits.ADON = 1;
    AD1CON1bits.SAMP = 1;
    AD1CON1bits.SAMP = 0;
    while(!AD1CON1bits.DONE);
    uint16_t result = ADC1BUF0;
    AD1CON1bits.ADON = 0;
    return result;
}




/*
 * File:   clkChange.c
 * Author: younn
 *
 * Created on October 3, 2024, 9:56 PM
 */

#include "clkChange.h"



void newClk(unsigned int clkval) {
    uint8_t COSCNOSC;
    switch(clkval) {
        case 8: // 8 MHz
            COSCNOSC = 0x00;
            break;
        case 500: // 500 kHz
            COSCNOSC = 0x66;
            break;
        case 32: // 32 kHz
            COSCNOSC = 0x55;
            break;
        default:
            COSCNOSC = 0x55;
    }
    SRbits.IPL = 7;
    CLKDIVbits.RCDIV = 0;
    __builtin_write_OSCCONH(COSCNOSC);
    __builtin_write_OSCCONL(0x01);
    while(OSCCONbits.OSWEN==1) {}
    SRbits.IPL = 0;
}




/*
 * File:   IOs.c
 * Author: younn
 *
 * Created on October 30, 2024, 1:15 PM
 */

#include <xc.h>
#include <stdint.h>
#include "UART2.h"
#include "ADC.h"
#include "IOs.h"
#include "timeDelay.h"

volatile uint8_t mode = 0;
volatile uint8_t pb1_pressed = 0;

void setup_IO(void) {
    TRISAbits.TRISA2 = 1;           // Configure RA2 as input.

    CNPU2bits.CN30PUE = 1;          // Enable pull-up resistor on CN30
    CNEN2bits.CN30IE = 1;           // Enable CN interrupt on CN30

    IPC4bits.CNIP = 6;              // Set CN interrupt priority to 6
    IFS1bits.CNIF = 0;              // Clear CN interrupt flag
    IEC1bits.CNIE = 1;              // Enable CN interrupts

    InitUART2();
    ADC_init();
}

void process_button(void) {
    if (pb1_pressed) {
        // Start debounce timer
        InitTimer2(20);

        // Wait for timer to finish
        while (!timer2_flag);
        timer2_flag = 0;

        // Check if button is still pressed
        if (!PORTAbits.RA2) {
            // Wait for button release
            while (!PORTAbits.RA2);

            // Toggle mode
            mode = !mode;
            if (mode == 0) {
                Disp2String("\rMode 0: Bar Graph Mode             ");
            } else {
                Disp2String("\rMode 1: Data Stream Mode           ");
            }
        }

        pb1_pressed = 0;
    }
}

void display_bargraph(uint16_t adc_value) {
    uint8_t bar_length = (adc_value * 32) / 1023;
    
    // Add carriage return to return to the beginning of the line
    Disp2String("\rMode 0: ");
    
    for (uint8_t i = 0; i < 32; i++) {
        XmitUART2((i < bar_length) ? '*' : ' ', 1);
    }
    
    Disp2String(" 0x");
    Disp2Hex(adc_value);
}

void send_adc_value(uint16_t adc_value) {
    Disp2Dec(adc_value);        // Send ADC value in decimal format
    XmitUART2('\n', 1);         // New line
}

void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) {
    if (!PORTAbits.RA2) {
        pb1_pressed = 1;
        // Optional: Disable CN interrupt temporarily
        IEC1bits.CNIE = 0; // Disable CN interrupts
        Disp2String("\rCN interrupt triggered!\r");
    }

    IFS1bits.CNIF = 0; // Clear the interrupt flag

    IEC1bits.CNIE = 1; // Re-enable CN interrupts (if you disabled them)
}




/*
 * File:   main.c
 * Author: Younnus Iman, Taiwu Chen, Farha Ahmed
 *
 * Created on October 30, 2024, 9:54 PM
 */
// FBS
#pragma config BWRP = OFF               // Table Write Protect Boot (Boot segment may be written)
#pragma config BSS = OFF                // Boot segment Protect (No boot program Flash segment)

// FGS
#pragma config GWRP = OFF               // General Segment Code Flash Write Protection bit (General segment may be written)
#pragma config GCP = OFF                // General Segment Code Flash Code Protection bit (No protection)

// FOSCSEL
#pragma config FNOSC = FRC              // Oscillator Select (Fast RC oscillator (FRC))
#pragma config IESO = OFF               // Internal External Switch Over bit (Internal External Switchover mode disabled (Two-Speed Start-up disabled))

// FOSC
#pragma config POSCMOD = NONE           // Primary Oscillator Configuration bits (Primary oscillator disabled)
#pragma config OSCIOFNC = ON            // CLKO Enable Configuration bit (CLKO output disabled; pin functions as port I/O)
#pragma config POSCFREQ = HS            // Primary Oscillator Frequency Range Configuration bits (Primary oscillator/external clock input frequency greater than 8 MHz)
#pragma config SOSCSEL = SOSCHP         // SOSC Power Selection Configuration bits (Secondary oscillator configured for high-power operation)
#pragma config FCKSM = CSECMD           // Clock Switching and Monitor Selection (Clock switching is enabled, Fail-Safe Clock Monitor is disabled)

// FWDT
#pragma config WDTPS = PS32768          // Watchdog Timer Postscale Select bits (1:32,768)
#pragma config FWPSA = PR128            // WDT Prescaler (WDT prescaler ratio of 1:128)
#pragma config WINDIS = OFF             // Windowed Watchdog Timer Disable bit (Standard WDT selected; windowed WDT disabled)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))

// FPOR
#pragma config BOREN = BOR3             // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware; SBOREN bit disabled)
#pragma config PWRTEN = ON              // Power-up Timer Enable bit (PWRT enabled)
#pragma config I2C1SEL = PRI            // Alternate I2C1 Pin Mapping bit (Default location for SCL1/SDA1 pins)
#pragma config BORV = V18               // Brown-out Reset Voltage bits (Brown-out Reset set to lowest voltage (1.8V))
#pragma config MCLRE = ON               // MCLR Pin Enable bit (MCLR pin enabled; RA5 input pin disabled)

// FICD
#pragma config ICS = PGx2               // ICD Pin Placement Select bits (PGC2/PGD2 are used for programming and debugging the device)

// FDS
#pragma config DSWDTPS = DSWDTPSF       // Deep Sleep Watchdog Timer Postscale Select bits (1:2,147,483,648 (25.7 Days))
#pragma config DSWDTOSC = LPRC          // DSWDT Reference Clock Select bit (DSWDT uses LPRC as reference clock)
#pragma config RTCOSC = SOSC            // RTCC Reference Clock Select bit (RTCC uses SOSC as reference clock)
#pragma config DSBOREN = ON             // Deep Sleep Zero-Power BOR Enable bit (Deep Sleep BOR enabled in Deep Sleep)
#pragma config DSWDTEN = ON             // Deep Sleep Watchdog Timer Enable bit (DSWDT enabled)

// #pragma config statements should precede project file includes.

#include "xc.h"
#include "ADC.h"
#include "IOs.h"
#include "clkChange.h"
#include "timeDelay.h"
#include "UART2.h"

int main(void) {
    newClk(500);
    AD1PCFG = 0xFFFF;
    setup_IO();
    InitTimer2(100);  // 100 ms delay
    uint16_t last_adc_value = 0;

    while(1) {
        Idle();

        process_button();  // Check the button at the start of each loop

        if(timer2_flag) {
            timer2_flag = 0;  // Reset the timer flag
            
            uint16_t adc_value = do_ADC();

            if(mode == 0) {
                // Mode 0: Update display only if the ADC value changed significantly
                if ((adc_value > last_adc_value && adc_value - last_adc_value > 10) || 
                    (adc_value < last_adc_value && last_adc_value - adc_value > 10)) {
                    display_bargraph(adc_value);
                    last_adc_value = adc_value; 
                }
            } else {
                // Mode 1: Always send ADC value
                send_adc_value(adc_value);
            }

            // Restart the timer for the next loop
            InitTimer2(100);
        }
    }

    return 0;
}





/*
 * File:   timeDelay.c
 * Author: younn
 *
 * Created on October 3, 2024, 10:19 PM
 */

#include "xc.h"
#include "timeDelay.h"

volatile uint8_t timer2_flag = 0;

void InitTimer2(uint16_t delay_ms) {
    T2CONbits.TCKPS = 0b10;       // 1:64 prescaler
    PR2 = (250 * delay_ms) / 64;  // Calculate PR2 for delay in ms at 500 kHz
    TMR2 = 0;
    IFS0bits.T2IF = 0;
    IEC0bits.T2IE = 1;
    T2CONbits.TON = 1;
}

void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void) {
    IFS0bits.T2IF = 0;
    timer2_flag = 1;
    T2CONbits.TON = 0;
}





/*
 * File:   UART2.c
 * Author: younn
 *
 * Created on October 3, 2024, 9:55 PM
 */


#include "xc.h"
#include "math.h"
#include "string.h"

#include "UART2.h"




unsigned int clkval;

///// Initialization of UART 2 module.

void InitUART2(void) 
{
	// configures UART2 module on pins RB0 (Tx) and RB1 (Rx) on PIC24F16KA101 
	// Enables UART2 
	//Set to Baud 4800 with 500kHz clk on PIC24F
	
	TRISBbits.TRISB0=0;
	TRISBbits.TRISB1=1;
	LATBbits.LATB0=1;

	// configure U2MODE
    U2MODE = 0b0000000000001000;
/*    
	U2MODEbits.UARTEN = 0;	// Bit15 TX, RX DISABLED, ENABLE at end of func
	U2MODEbits.USIDL = 0;	// Bit13 Continue in Idle
	U2MODEbits.IREN = 0;	// Bit12 No IR translation
	U2MODEbits.RTSMD = 0;	// Bit11 Simplex Mode
	U2MODEbits.UEN = 0;		// Bits8,9 TX,RX enabled, CTS,RTS not
	U2MODEbits.WAKE = 0;	// Bit7 No Wake up (since we don't sleep here)
	U2MODEbits.LPBACK = 0;	// Bit6 No Loop Back
	U2MODEbits.ABAUD = 0;	// Bit5 No Autobaud (would require sending '55')
	U2MODEbits.RXINV = 0;	// Bit4 IdleState = 1
	U2MODEbits.BRGH = 1;	// Bit3 16 clocks per bit period
	U2MODEbits.PDSEL = 0;	// Bits1,2 8bit, No Parity
	U2MODEbits.STSEL = 0;	// Bit0 One Stop Bit
 */
	if (OSCCONbits.COSC == 0b110)
	{
		U2BRG = 12;	// gives a baud rate of 4807.7 Baud with 500kHz clock; Set Baud to 4800 on realterm
	}
	else if (OSCCONbits.COSC == 0b101)
	{
		U2BRG = 12;	// gives a baud rate of 300 Baud with 32kHz clock; set Baud to 300 on realterm
	}
	else if (OSCCONbits.COSC == 0b000)
	{
		U2BRG=103;	// gives a baud rate of 9600 with 8MHz clock; set Baud to 9600 on real term
	}
	// Load all values in for U1STA SFR
	U2STA = 0b1010000000000000;
    /*
    U2STAbits.UTXISEL1 = 1;	//Bit15 Int when Char is transferred (1/2 config!)
    U2STAbits.UTXISEL0 = 1;	//Generate interrupt with last character shifted out of U2TXREG buffer
	U2STAbits.UTXINV = 0;	//Bit14 N/A, IRDA config
	U2STAbits.UTXBRK = 0;	//Bit11 Disabled
	U2STAbits.UTXEN = 0;	//Bit10 TX pins controlled by periph
	U2STAbits.UTXBF = 0;	//Bit9 *Read Only Bit*
	U2STAbits.TRMT = 0;		//Bit8 *Read Only bit*
	U2STAbits.URXISEL = 0;	//Bits6,7 Int. on character recieved
	U2STAbits.ADDEN = 0;	//Bit5 Address Detect Disabled
	U2STAbits.RIDLE = 0;	//Bit4 *Read Only Bit*
	U2STAbits.PERR = 0;		//Bit3 *Read Only Bit*
	U2STAbits.FERR = 0;		//Bit2 *Read Only Bit*
	U2STAbits.OERR = 0;		//Bit1 *Read Only Bit*
	U2STAbits.URXDA = 0;	//Bit0 *Read Only Bit*
    */
	IFS1bits.U2TXIF = 0;	// Clear the Transmit Interrupt Flag
    IPC7bits.U2TXIP = 3; // UART2 TX interrupt has interrupt priority 3-4th highest priority
    
	IEC1bits.U2TXIE = 1;	// Enable Transmit Interrupts
	IFS1bits.U2RXIF = 0;	// Clear the Recieve Interrupt Flag
	IPC7bits.U2RXIP = 4; //UART2 Rx interrupt has 2nd highest priority
    IEC1bits.U2RXIE = 0;	// Disable Recieve Interrupts

	U2MODEbits.UARTEN = 1;	// And turn the peripheral on

	U2STAbits.UTXEN = 1;
	return;
}



///// XmitUART2: 
///// Displays 'DispData' on realterm 'repeatNo' of times using UART to PC. 
///// Adjust Baud on real term as per clock: 32kHz clock - Baud=300 // 500kHz clock - Baud=4800 

void XmitUART2(char CharNum, unsigned int repeatNo)
{	
	
	InitUART2();	//Initialize UART2 module and turn it on
	while(repeatNo!=0) 
	{
		while(U2STAbits.UTXBF==1)	//Just loop here till the FIFO buffers have room for one more entry
		{
			// Idle();  //commented to try out serialplot app
		}	
		U2TXREG=CharNum;	//Move Data to be displayed in UART FIFO buffer
		repeatNo--;
	}
	while(U2STAbits.TRMT==0)	//Turn off UART2 upon transmission of last character; also can be Verified in interrupt subroutine U2TXInterrupt()
	{
		//Idle();
	}
	U2MODEbits.UARTEN = 0;	
	return;
}


void __attribute__ ((interrupt, no_auto_psv)) _U2RXInterrupt(void) {
//	LATA = U2RXREG;
	IFS1bits.U2RXIF = 0;
}
void __attribute__ ((interrupt, no_auto_psv)) _U2TXInterrupt(void) {
	IFS1bits.U2TXIF = 0;

}




// Displays 16 bit number in Hex form using UART2
void Disp2Hex(unsigned int DispData)   
{
    char i;
    char nib = 0x00;
    XmitUART2(' ',1);  // Disp Gap
    XmitUART2('0',1);  // Disp Hex notation 0x
    XmitUART2('x',1);
    
    for (i=3; i>=0; i--)
    {
        nib = ((DispData >> (4*i)) & 0x000F);
        if (nib >= 0x0A)
        {
            nib = nib +0x37;  //For Hex values A-F
        }
        else 
        {
            nib = nib+0x30;  //For hex values 0-9
        }
        XmitUART2(nib,1);
    }
    
    XmitUART2(' ',1);
    DispData = 0x0000;  // Clear DispData
    return;
}


void Disp2Hex32(unsigned long int DispData32)   // Displays 32 bit number in Hex form using UART2
{
    char i;
    char nib = 0x00;
    XmitUART2(' ',1);  // Disp Gap
    XmitUART2('0',1);  // Disp Hex notation 0x
    XmitUART2('x',1);
    
    for (i=7; i>=0; i--)
    {
        nib = ((DispData32 >> (4*i)) & 0x000F);
        if (nib >= 0x0A)
        {
            nib = nib +0x37;  //For Hex values A-F
        }
        else 
        {
            nib = nib+0x30;  //For hex values 0-9
        }
        XmitUART2(nib,1);
    }
    
    XmitUART2(' ',1);
    DispData32 = 0x00000000;  // Clear DispData
    return;
}

// Displays 16 bit unsigned in in decimal form
void Disp2Dec(uint16_t Dec_num)
{
    uint8_t rem;  //remainder in div by 10
    uint16_t quot; 
    uint8_t ctr = 0;  //counter
    XmitUART2(' ',1);  // Disp Gap
    while(ctr<5)
    {
        quot = Dec_num/(pow(10,(4-ctr)));
        rem = quot%10;
        XmitUART2(rem + 0x30 , 1);
        ctr = ctr + 1;
    }
    XmitUART2(' ',1);  // Disp Gap
    // XmitUART2('\n',1);  // new line
    // XmitUART2('\r',1);  // carriage return
   
    return;
}


void Disp2String(char *str) //Displays String of characters
{
    unsigned int i;
   // XmitUART2(0x0A,2);  //LF
   // XmitUART2(0x0D,1);  //CR 
    for (i=0; i<= strlen(str); i++)
    {
          
        XmitUART2(str[i],1);
    }
    // XmitUART2(0x0A,2);  //LF
    // XmitUART2(0x0D,1);  //CR 
    
    return;
}



here is code for an older assignment now I have to do this:


App Project 2: LED Intensity Controller (Group Project)
Due Date: As per D2L Dropbox
Assignment: Using the Microcontroller and your experience from developing driver functions developed so far,
you will design an “LED Light Control” App to control the brightness/ intensity of an LED connected to pin 12.
You will also log the brightness setting on your PC with a Python program that you must design and implement.
The requirements that your project must satisfy are described in this brief. The push buttons are defined as in
the previous assignments and should be connected to the same pins as before. We define a push button “click”
as a press and release of a button.
User input(s) Output(s)
If PB1 is clicked (i.e.,
there should be no need
to “hold down” the
button)
After programming the microcontroller, if PB1 is clicked, it should put the System
in ON MODE. In this mode, the LED should turn on. Turning the potentiometer
should adjust the LED intensity to between full brightness and 0% (LED off).
The variable brightness must be achieved by using Pulse width modulation of the
signal supplied to the LED as described below.
If PB1 is pressed again, the System should enter OFF mode, i.e., turn off the LED
and put the system in low-power Idle() mode.
If PB2 is clicked (i.e.,
there should be no need
to “hold down” the
button)
While in ON MODE, if PB2 is pressed once, it should blink the LED. When the LED
is on during the blink, it should be at the intensity level corresponding to the
current ADC reading. When the LED is off during the blink, the intensity is 0. The
blinking should happen at approx. 500 ms intervals (0.5 s on, 0.5 s off). If you turn
the potentiometer, the intensity while blinking should adjust accordingly.
While in OFF MODE, if PB2 is pressed once, it should blink the LED at 100%
intensity level at approx. 500 ms intervals (0.5 s on, 0.5 s off).
The LED blinking should stop if PB2 is clicked again in either mode.
If PB3 is clicked (i.e.,
there should be no need
to “hold down” the
button)
If PB3 is clicked during the ON MODE (non-blink) or ON MODE (blink), the
microcontroller should start to transmit the intensity level and ADC reading to a
PC over UART. On the PC, you should design and implement a Python script to
receive the UART transmissions. For a period of 1 minute:
1. Capture and Store the intensity levels (0-100%) of the LED and the ADC
readings from the microcontroller, in a single CSV file with appropriate
indexing and column names. You should time-stamp the readings
appropriately.
2. After 1 minute, you should produce a graph/plot of the intensity levels
(0-100%) vs. time (in seconds) and another graph of the ADC reading vs.
time (i.e., two separate graphs, that could be subplots).
Your graphs must have an appropriate title and axes labels. The generated CSV
file should be named as per your group name and have proper index numbers
and column names. In order to capture the LED blinking properly, you will need
to transmit data at a rate of more than 2 Hz. Note that while the LED is off
(during a blink), we would expect the “intensity” readings to be 0%.
ALL SECTIONS: Version 1
ENSF 460, Fall 2024 | R. Vyas / B. Tan
Clicking PB3 again, or leaving the ON MODE, should stop the UART transmissions.
While transmitting, it must be possible for a user to go back and forth between
blink and non-blink modes and have the transmitted data/generate graph show
the transition. Note that UART transmissions should only occur after PB3 has
been clicked as described above.
Additional info:
Implement the above controller in C as a finite-state machine-based controller, to run on your hardware kit. You
must not use the Output Compare/PWM peripheral in this project. Polling of PORTx or TMRx directly, or
corresponding flags that you create, instead of interrupt-driven programming, may lose points. Note that you
may use multiple timer peripherals or the 32-bit timer configuration at your discretion. You might recall that
there are three timers available to you. You will need to navigate the datasheet by yourselves, accordingly.
Your implementation should be as power-efficient as possible. You may implement “polling-like” behavior to
read your ADC and determine when to send data over UART.
Function names: You may use any convention when naming functions or organizing code. A state diagram of
your design is required as part of your submission. Use microcontroller-specific registers, bit names, and flags (to
jump between states) wherever applicable in the state diagram. Your C code must accurately reflect your FSM
and vice versa.
Display instructions: All displays on the PC should be using Python. Note that display functions carried out at 32
kHz (300 Baud) can affect timer delays. Your code should account for such delays when producing delays
specified in the table above. You may choose to use whatever clock speed(s) available to you as you see fit.
Interrupts: Interrupt ISR names are provided in the lecture slides. As specified in lectures, IO (CN interrupts) are
triggered on rising and falling edges and due to any bounce effects of the push buttons that cause several high-
to-low and low-to-high fluctuations at the Microcontroller input. Your code should filter out any such effects.
Note: the “click” behavior descriptions above suggest that your system must not change state just because a
button is pressed (so a press and hold down should not cause a behavior change), but the button being released
should.
Your submission must satisfy the following in addition to achieving all requirements of this project and
delivering all deliverables to gain full marks: (i) You do not call functions in an ISR (this includes no UART
messages in the ISR), unless you can prove that the function(s) called are reentrant (ii) You do not have infinite
loops in an ISR, (iii) You do not add delays to the ISR, (iv) You do not poll the input ports (i.e., your program
should not be repeatedly testing (reading) the value of the PORTA or PORTB, (v) Your submission should not
have “glitches” (e.g., pushing the buttons in an arbitrary order at arbitrary times should not result in unexpected
behavior), (vi) your C program does not poll status flags related to the timers or inputs, and (vii) there should not
be any visual flickering of the LED. You may submit a project that does not satisfy all requirements but will only
receive partial credit. All members of your group must be in attendance at the demo.
You are responsible for regularly checking D2L for announcements (e.g., via the News tool) regarding the
project. As with any engineering project, requirements and guidance are subject to change at the teaching
team’s discretion. If you require clarification, it is your responsibility to discuss your thoughts with the instructor
during the timetabled class times.
ALL SECTIONS: Version 1
ENSF 460, Fall 2024 | R. Vyas / B. Tan
Pulse Width Modulated Signals (PWM):
PWM signals are commonly used in many mechatronic applications like light and motor control, etc., and look
like Figures 1 and 2 below. You will program the microcontroller to generate a PWM signal from Pin 12,
connected to an LED via a 1K-ohm current limiting resistor. The duty cycle should be controllable based on the
Potentiometer input.
(Figure Sources: realdigital.org)
Figure 1: Relationship between PWM Duty cycle and LED brightness or intensity levels
Vpwm = Duty Cycle/100 * VDD, where
Vpwm: PWM voltage or average voltage of a PWM Signal
VDD: Voltage supplied on a Microcontroller pin
Figure 2: PWM Signal
Pulse Frequency: You can use any pulse frequency for your app. However, the pulse frequency should be high
enough so that the resulting LED flicker is not visible to the human eye but, at the same time, not too high to
consume excessive power. Use trial and error when coding your app to determine an appropriate Pulse
Frequency.


few things that you need to know

    TRISBbits.TRISB8 = 0;  // LED as output
    
    TRISAbits.TRISA2 = 1;  // PB1 as input
    TRISBbits.TRISB4 = 1;  // PB2 as input
    TRISAbits.TRISA4 = 1;  // PB3 as input

right now the UART display keeps displaying the updates on new lines, despite whatever we do including using \r instead of \n, we want it to just update the line and not continue outputing multiple new lines, ideally by erasing the previous output and inputing the new one over it or perhaps something else if possible. We also need a python file as specified by the assignment, please show me the code that would change according to this assignment
ASSISTANT
Certainly! Let's break down your project into manageable sections to ensure you meet all requirements effectively. We'll cover the following:

1. **Overview of the Solution**
2. **C Code Modifications**
   - Finite-State Machine (FSM) Design
   - Software PWM Implementation
   - Button Handling and State Transitions
   - UART Transmission Adjustments
   - Fixing UART Display to Update on the Same Line
3. **Python Script for UART Data Logging and Plotting**

---

## 1. Overview of the Solution

Your project involves designing an LED Intensity Controller with the following functionalities:

- **Mode Control**: Toggle between ON and OFF modes using PB1.
- **Blinking Control**: Toggle LED blinking using PB2.
- **Data Logging**: Start/stop UART data transmission using PB3.
- **PWM-Based Brightness Control**: Adjust LED intensity based on ADC readings using PWM implemented in software.
- **UART Display Refinement**: Ensure UART data updates occur on the same line without creating new lines each time.
- **Python Script**: Capture UART data, log it to a CSV file, and generate plots after one minute.

We'll implement these functionalities by modifying your existing C code and creating a Python script.

---

## 2. C Code Modifications

### 2.1. Finite-State Machine (FSM) Design

We'll design the FSM to manage different states based on button interactions:

- **Modes**:
  - `OFF`: LED is off.
  - `ON`: LED is on with adjustable brightness via PWM.
  
- **Blinking**:
  - `BLINK_OFF`: No blinking.
  - `BLINK_ON`: Blinking is active.

- **UART Transmission**:
  - `UART_STOPPED`: No data transmission.
  - `UART_STARTED`: Data transmission is active.

**State Variables**:
```c
typedef enum {
    MODE_OFF,
    MODE_ON
} SystemMode;

typedef enum {
    BLINK_OFF,
    BLINK_ON
} BlinkMode;

typedef enum {
    UART_STOPPED,
    UART_STARTED
} UARTMode;

volatile SystemMode system_mode = MODE_OFF;
volatile BlinkMode blink_mode = BLINK_OFF;
volatile UARTMode uart_mode = UART_STOPPED;
```

### 2.2. Software PWM Implementation

Since you cannot use hardware PWM peripherals, we'll implement PWM manually using a timer interrupt (Timer3). Here's how:

- **PWM Frequency**: 100 Hz (10 ms period)
- **PWM Resolution**: 100 steps (1% per step)

**Variables**:
```c
#define PWM_PERIOD_MS 10
volatile uint8_t pwm_duty_cycle = 0; // 0-100
volatile uint8_t pwm_counter = 0;
volatile uint8_t pwm_state = 0; // 0: Off, 1: On
```

**PWM Initialization**:
```c
void PWM_init(void) {
    // Configure Timer3 for 1 ms interrupts (assuming 500 kHz clock)
    T3CONbits.TCKPS = 0b01; // Prescaler 1:8
    PR3 = 50000 / 8 / 1000 - 1; // For 1 ms interrupts
    TMR3 = 0;
    IEC0bits.T3IE = 1; // Enable Timer3 interrupt
    IFS0bits.T3IF = 0; // Clear Timer3 interrupt flag
    T3CONbits.TON = 1; // Start Timer3
}
```

**PWM Interrupt Service Routine (ISR)**:
```c
void __attribute__((interrupt, no_auto_psv)) _T3Interrupt(void) {
    IFS0bits.T3IF = 0; // Clear Timer3 interrupt flag
    
    if (pwm_counter < pwm_duty_cycle) {
        LATBbits.LATB8 = 1; // Turn LED on
    } else {
        LATBbits.LATB8 = 0; // Turn LED off
    }

    pwm_counter++;
    if (pwm_counter >= 100) { // Reset every 100 ms
        pwm_counter = 0;
    }
}
```

**Explanation**:
- The Timer3 ISR executes every 1 ms.
- `pwm_duty_cycle` determines how many milliseconds the LED stays on within the 10 ms period.
- `pwm_counter` increments each millisecond. If it's less than `pwm_duty_cycle`, the LED is on; otherwise, it's off.
- This achieves a PWM duty cycle with 1% resolution.

### 2.3. Button Handling and State Transitions

We'll handle button clicks using existing CN interrupts with debouncing. Here's how to manage state transitions based on button presses:

**Button Processing Function**:
```c
void process_button(void) {
    if (pb1_pressed) {
        // Debounce handled elsewhere
        if (system_mode == MODE_OFF) {
            system_mode = MODE_ON;
            Disp2String("\rMode: ON\t");
            // Start PWM
            PWM_init();
        } else {
            system_mode = MODE_OFF;
            Disp2String("\rMode: OFF\t");
            // Stop PWM
            T3CONbits.TON = 0;
            LATBbits.LATB8 = 0; // Ensure LED is off
        }
        pb1_pressed = 0;
    }

    if (pb2_pressed) {
        // Debounce handled elsewhere
        if (blink_mode == BLINK_OFF) {
            blink_mode = BLINK_ON;
            Disp2String("\rBlink: ON\t");
            InitTimer4(500); // 500 ms intervals for blinking
        } else {
            blink_mode = BLINK_OFF;
            Disp2String("\rBlink: OFF\t");
            // Stop blinking
            T4CONbits.TON = 0;
            LATBbits.LATB8 = (system_mode == MODE_ON) ? 1 : 0;
        }
        pb2_pressed = 0;
    }

    if (pb3_pressed) {
        // Debounce handled elsewhere
        if (uart_mode == UART_STOPPED) {
            uart_mode = UART_STARTED;
            Disp2String("\rUART: STARTED\t");
        } else {
            uart_mode = UART_STOPPED;
            Disp2String("\rUART: STOPPED\t");
        }
        pb3_pressed = 0;
    }
}
```

**Explanation**:
- **PB1**: Toggles between ON and OFF modes. Initializes or stops PWM accordingly.
- **PB2**: Toggles blinking. Initializes a separate timer (Timer4) for blinking intervals.
- **PB3**: Toggles UART data transmission state.

**Blinking Implementation with Timer4**:
```c
volatile uint8_t blink_flag = 0;

void InitTimer4(uint16_t delay_ms) {
    T4CONbits.TCKPS = 0b10; // Prescaler 1:64
    PR4 = (500 * 500) / 64 - 1; // 500 ms delay
    TMR4 = 0;
    IFS1bits.T4IF = 0;
    IEC1bits.T4IE = 1; // Enable Timer4 interrupt
    T4CONbits.TON = 1; // Start Timer4
}

void __attribute__((interrupt, no_auto_psv)) _T4Interrupt(void) {
    IFS1bits.T4IF = 0; // Clear Timer4 interrupt flag
    blink_flag = 1;
}

void handle_blinking(void) {
    if (blink_flag) {
        blink_flag = 0;
        if (blink_mode == BLINK_ON) {
            if (LATBbits.LATB8) {
                LATBbits.LATB8 = (system_mode == MODE_ON) ? 1 : 0;
            } else {
                LATBbits.LATB8 = 0;
            }
        } else if (blink_mode == BLINK_OFF) {
            LATBbits.LATB8 = (LATBbits.LATB8) ? 0 : 1;
        }
    }
}
```

**Explanation**:
- **Timer4**: Generates an interrupt every 500 ms.
- **handle_blinking()**: Toggles the LED state based on `blink_mode`.

### 2.4. UART Transmission Adjustments

We'll adjust the UART transmission to handle data logging based on `uart_mode`. We'll send data periodically (e.g., every 500 ms) when UART is active.

**Variables**:
```c
volatile uint8_t uart_timer_flag = 0;
```

**UART Timer Initialization (Timer5 for UART transmission)**:
```c
void InitTimer5(uint16_t delay_ms) {
    T5CONbits.TCKPS = 0b10; // Prescaler 1:64
    PR5 = (500 * 500) / 64 - 1; // 500 ms delay
    TMR5 = 0;
    IFS0bits.T5IF = 0;
    IEC0bits.T5IE = 1; // Enable Timer5 interrupt
    T5CONbits.TON = 1; // Start Timer5
}

void __attribute__((interrupt, no_auto_psv)) _T5Interrupt(void) {
    IFS0bits.T5IF = 0; // Clear Timer5 interrupt flag
    uart_timer_flag = 1;
}
```

**Modify `process_button` for UART Initialization**:
```c
if (uart_mode == UART_STARTED) {
    InitTimer5(500); // Initialize Timer5 for UART data transmission every 500 ms
} else {
    T5CONbits.TON = 0; // Stop Timer5
}
```

**UART Data Transmission in Main Loop**:
```c
if (uart_timer_flag) {
    uart_timer_flag = 0;
    uint16_t adc_value = do_ADC();
    uint8_t intensity = (pwm_duty_cycle); // Assuming 0-100%
    
    // Format data as "Intensity,ADC\r"
    char uart_buffer[20];
    sprintf(uart_buffer, "I:%d,ADC:%d\r", intensity, adc_value);
    Disp2String(uart_buffer); // Modify Disp2String to handle UART transmission properly
}
```

**Explanation**:
- **Timer5**: Triggers every 500 ms to send UART data.
- **UART Data**: Sent in the format `I:<intensity>,ADC:<adc_value>\r`.

### 2.5. Fixing UART Display to Update on the Same Line

To ensure UART data updates occur on the same line, use carriage return `\r` without newline `\n`. Additionally, ensure the terminal interprets `\r` correctly.

**Modify `Disp2String` Function**:
```c
void Disp2String(char *str) // Displays String of characters
{
    unsigned int i;
    for (i = 0; i < strlen(str); i++) // Changed to < instead of <= to avoid sending the null terminator
    {
        XmitUART2(str[i], 1);
    }
    return;
}
```

**Usage in UART Transmission**:
Ensure that each UART message starts with `\r` to return the cursor to the beginning of the line.
```c
sprintf(uart_buffer, "\rI:%d,ADC:%d", intensity, adc_value);
Disp2String(uart_buffer);
```

**Explanation**:
- **`\r`**: Moves the cursor to the beginning of the line.
- **Avoid `\n`**: Prevents moving to a new line.
- **Terminal Settings**: Ensure your terminal software (e.g., RealTerm, PuTTY) is set to interpret `\r` correctly. Some terminals may require specific settings to prevent automatic line feeds.

**Optional Enhancement**: Use ANSI escape codes for more control (e.g., clearing the line), but this depends on the terminal's support.

---

## 3. Python Script for UART Data Logging and Plotting

We'll create a Python script that:

1. **Connects to the Microcontroller via UART**.
2. **Receives UART Data** in the format `I:<intensity>,ADC:<adc_value>`.
3. **Logs Data** to a CSV file with timestamps.
4. **After 1 Minute**, generates plots for intensity vs. time and ADC reading vs. time.

**Prerequisites**:
- Install `pyserial` and `matplotlib` libraries:
  ```bash
  pip install pyserial matplotlib pandas
  ```

**Python Script** (`uart_data_logger.py`):
```python
import serial
import time
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime

# Configure serial port (update 'COM3' and baud rate as per your setup)
SERIAL_PORT = 'COM3'
BAUD_RATE = 4800  # Adjust based on microcontroller UART settings

# Initialize serial connection
ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)

# Initialize data storage
data = {
    'Timestamp': [],
    'Intensity': [],
    'ADC_Value': []
}

print("Starting data logging for 1 minute...")

start_time = time.time()
duration = 60  # 60 seconds

while (time.time() - start_time) < duration:
    if ser.in_waiting:
        line = ser.readline().decode('utf-8').strip()
        if line:
            # Expected format: "I:<intensity>,ADC:<adc_value>"
            try:
                parts = line.split(',')
                intensity = int(parts[0].split(':')[1])
                adc = int(parts[1].split(':')[1])
                timestamp = datetime.now().strftime('%H:%M:%S')
                
                data['Timestamp'].append(timestamp)
                data['Intensity'].append(intensity)
                data['ADC_Value'].append(adc)
                
                print(f"{timestamp} - Intensity: {intensity}%, ADC: {adc}")
            except (IndexError, ValueError) as e:
                print(f"Error parsing line: {line} ({e})")
    time.sleep(0.1)  # Small delay to prevent high CPU usage

ser.close()
print("Data logging complete.")

# Create DataFrame
df = pd.DataFrame(data)

# Save to CSV
csv_filename = f"group_data_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
df.to_csv(csv_filename, index=False)
print(f"Data saved to {csv_filename}")

# Plotting
plt.figure(figsize=(12, 6))

# Plot Intensity
plt.subplot(2, 1, 1)
plt.plot(df['Timestamp'], df['Intensity'], label='Intensity (%)', color='blue')
plt.title('LED Intensity Over Time')
plt.ylabel('Intensity (%)')
plt.xticks(rotation=45)
plt.grid(True)

# Plot ADC Values
plt.subplot(2, 1, 2)
plt.plot(df['Timestamp'], df['ADC_Value'], label='ADC Reading', color='green')
plt.title('ADC Reading Over Time')
plt.xlabel('Time')
plt.ylabel('ADC Value')
plt.xticks(rotation=45)
plt.grid(True)

plt.tight_layout()
plt.savefig(f"group_data_plot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png")
plt.show()
print("Plots generated.")
```

**Explanation**:

1. **Serial Configuration**:
   - Update `SERIAL_PORT` and `BAUD_RATE` to match your microcontroller's settings.
   
2. **Data Reception**:
   - The script reads incoming UART data line by line.
   - It expects data in the format `I:<intensity>,ADC:<adc_value>`.
   - Parses intensity and ADC values and appends them to the `data` dictionary with timestamps.

3. **Data Logging**:
   - After 1 minute, the data is saved to a CSV file named with the current date and time.

4. **Plotting**:
   - Generates two subplots:
     - **Intensity vs. Time**: Shows LED brightness over time.
     - **ADC Value vs. Time**: Shows ADC readings over time.
   - Saves the plot as a PNG file and displays it.

**Usage**:

1. **Run the C Microcontroller Code**: Ensure your microcontroller firmware is running and sending UART data.
2. **Run the Python Script**:
   ```bash
   python uart_data_logger.py
   ```
3. **Observing Outputs**:
   - The script prints incoming data to the console.
   - After 1 minute, it saves the data to a CSV file and generates plots.

---

## Complete C Code Integration

Below is an integrated version of the necessary C code modifications. Ensure you incorporate these into your existing codebase appropriately.

**Headers and Global Variables**:
```c
#include "xc.h"
#include "ADC.h"
#include "UART2.h"
#include "IOs.h"
#include "clkChange.h"
#include "timeDelay.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

// FSM States
typedef enum {
    MODE_OFF,
    MODE_ON
} SystemMode;

typedef enum {
    BLINK_OFF,
    BLINK_ON
} BlinkMode;

typedef enum {
    UART_STOPPED,
    UART_STARTED
} UARTMode;

// Global Variables
volatile SystemMode system_mode = MODE_OFF;
volatile BlinkMode blink_mode = BLINK_OFF;
volatile UARTMode uart_mode = UART_STOPPED;

volatile uint8_t pb1_pressed = 0;
volatile uint8_t pb2_pressed = 0;
volatile uint8_t pb3_pressed = 0;

// PWM Variables
#define PWM_PERIOD_MS 10
volatile uint8_t pwm_duty_cycle = 0; // 0-100%
volatile uint8_t pwm_counter = 0;

// Blinking Variables
volatile uint8_t blink_flag = 0;

// UART Transmission Variables
volatile uint8_t uart_timer_flag = 0;

void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void) {
    if (!PORTAbits.RA2) {
        pb1_pressed = 1;
    }
    if (!PORTBbits.RB4) {
        pb2_pressed = 1;
    }
    if (!PORTAbits.RA4) {
        pb3_pressed = 1;
    }

    IFS1bits.CNIF = 0; // Clear CN interrupt flag
}

void __attribute__((interrupt, no_auto_psv)) _T3Interrupt(void) {
    IFS0bits.T3IF = 0; // Clear Timer3 interrupt flag

    if (pwm_counter < pwm_duty_cycle) {
        LATBbits.LATB8 = 1; // Turn LED on
    } else {
        LATBbits.LATB8 = 0; // Turn LED off
    }

    pwm_counter++;
    if (pwm_counter >= 100) { // Reset every 100 ms
        pwm_counter = 0;
    }
}

void __attribute__((interrupt, no_auto_psv)) _T4Interrupt(void) {
    IFS1bits.T4IF = 0; // Clear Timer4 interrupt flag
    blink_flag = 1;
}

void __attribute__((interrupt, no_auto_psv)) _T5Interrupt(void) {
    IFS0bits.T5IF = 0; // Clear Timer5 interrupt flag
    uart_timer_flag = 1;
}
```

**Initialization Functions**:
```c
void setup_IO(void) {
    // Configure LED pin as output
    TRISBbits.TRISB8 = 0; // LED as output
    LATBbits.LATB8 = 0; // Ensure LED is off

    // Configure PB1, PB2, PB3 as inputs
    TRISAbits.TRISA2 = 1; // PB1 as input
    TRISBbits.TRISB4 = 1; // PB2 as input
    TRISAbits.TRISA4 = 1; // PB3 as input

    // Enable pull-up resistors
    CNPU1bits.CN0PUE = 1; // Assuming PB1 is CN0
    CNPU1bits.CN1PUE = 1; // Assuming PB2 is CN1
    CNPU1bits.CN2PUE = 1; // Assuming PB3 is CN2

    // Enable CN interrupts
    CNEN1bits.CN0IE = 1; // PB1
    CNEN1bits.CN1IE = 1; // PB2
    CNEN1bits.CN2IE = 1; // PB3

    // Set interrupt priority
    IPC4bits.CNIP = 6; // CN interrupt priority to 6

    // Clear interrupt flags
    IFS1bits.CNIF = 0;

    // Enable CN interrupts
    IEC1bits.CNIE = 1;

    // Initialize UART
    InitUART2();

    // Initialize ADC
    ADC_init();
}

void InitPWM(void) {
    // Configure Timer3 for PWM
    T3CONbits.TCKPS = 0b01; // Prescaler 1:8
    PR3 = (500000 / 8 / 1000) - 1; // 1 ms interrupts for 100 Hz PWM
    TMR3 = 0;
    IPC3bits.T3IP = 5; // Timer3 interrupt priority
    IEC0bits.T3IE = 1; // Enable Timer3 interrupt
    IFS0bits.T3IF = 0; // Clear Timer3 interrupt flag
}

void InitBlink(void) {
    // Configure Timer4 for blinking (500 ms)
    T4CONbits.TCKPS = 0b10; // Prescaler 1:64
    PR4 = (500 * 500) / 64 - 1; // 500 ms delay
    TMR4 = 0;
    IPC5bits.T4IP = 5; // Timer4 interrupt priority
    IEC1bits.T4IE = 1; // Enable Timer4 interrupt
    IFS1bits.T4IF = 0; // Clear Timer4 interrupt flag
}

void InitUARTTransmissionTimer(void) {
    // Configure Timer5 for UART transmission (500 ms)
    T5CONbits.TCKPS = 0b10; // Prescaler 1:64
    PR5 = (500 * 500) / 64 - 1; // 500 ms delay
    TMR5 = 0;
    IPC7bits.T5IP = 5; // Timer5 interrupt priority
    IEC0bits.T5IE = 1; // Enable Timer5 interrupt
    IFS0bits.T5IF = 0; // Clear Timer5 interrupt flag
}
```

**Main Function**:
```c
int main(void) {
    newClk(500); // Initialize clock to 500 kHz
    AD1PCFG = 0xFFFF; // Configure all ANx as digital

    setup_IO(); // Initialize IOs

    while (1) {
        Idle(); // Enter low-power mode

        process_button(); // Handle button presses

        if (blink_flag) {
            blink_flag = 0;
            if (blink_mode == BLINK_ON) {
                if (system_mode == MODE_ON) {
                    LATBbits.LATB8 = !LATBbits.LATB8; // Toggle LED
                } else if (system_mode == MODE_OFF) {
                    LATBbits.LATB8 = !LATBbits.LATB8; // Toggle LED at 100% brightness
                }
            }
        }

        if (uart_timer_flag && uart_mode == UART_STARTED) {
            uart_timer_flag = 0;
            uint16_t adc_value = do_ADC();
            uint8_t intensity = pwm_duty_cycle; // 0-100%

            // Format UART message
            char uart_buffer[20];
            sprintf(uart_buffer, "\rI:%d,ADC:%d", intensity, adc_value);
            Disp2String(uart_buffer);
        }
    }

    return 0;
}
```

**Button Processing Function (Expanded)**:
```c
void process_button(void) {
    if (pb1_pressed) {
        // Toggle system mode
        if (system_mode == MODE_OFF) {
            system_mode = MODE_ON;
            Disp2String("\rMode: ON\t");
            InitPWM(); // Start PWM
        } else {
            system_mode = MODE_OFF;
            Disp2String("\rMode: OFF\t");
            T3CONbits.TON = 0; // Stop PWM
            LATBbits.LATB8 = 0; // Ensure LED is off
        }
        pb1_pressed = 0;
    }

    if (pb2_pressed) {
        // Toggle blink mode
        if (blink_mode == BLINK_OFF) {
            blink_mode = BLINK_ON;
            Disp2String("\rBlink: ON\t");
            InitBlink(); // Start blinking
        } else {
            blink_mode = BLINK_OFF;
            Disp2String("\rBlink: OFF\t");
            T4CONbits.TON = 0; // Stop blinking
            LATBbits.LATB8 = (system_mode == MODE_ON) ? 1 : 0; // Restore LED state
        }
        pb2_pressed = 0;
    }

    if (pb3_pressed) {
        // Toggle UART transmission
        if (uart_mode == UART_STOPPED) {
            uart_mode = UART_STARTED;
            Disp2String("\rUART: STARTED\t");
            InitUARTTransmissionTimer(); // Start UART timer
        } else {
            uart_mode = UART_STOPPED;
            Disp2String("\rUART: STOPPED\t");
            T5CONbits.TON = 0; // Stop UART timer
        }
        pb3_pressed = 0;
    }
}
```

**Final Notes**:

- **ISR Priorities**: Ensure that all ISRs have appropriate priorities to prevent conflicts.
- **Debouncing**: The current implementation assumes that button debouncing is handled elsewhere. If not, consider implementing it using timers or state checks.
- **UART Display**: Test the UART display with your terminal software to ensure that `\r` behaves as expected. You might need to adjust terminal settings or implement additional logic if necessary.
- **Power Efficiency**: Using low-power `Idle()` mode and efficient ISR handling helps maintain power efficiency.
- **Testing**: Thoroughly test each functionality (mode toggling, blinking, UART transmission) individually before integrating all features.

---

## 4. Python Script for UART Data Logging and Plotting

Here's a complete Python script tailored to your project requirements.

**Python Script (`uart_data_logger.py`)**:
```python
import serial
import time
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime

def main():
    # Configure serial port parameters
    SERIAL_PORT = 'COM3'  # Update to your port (e.g., 'COM3' on Windows or '/dev/ttyUSB0' on Linux)
    BAUD_RATE = 4800       # Must match the microcontroller's baud rate

    # Initialize serial connection
    try:
        ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=1)
    except serial.SerialException as e:
        print(f"Error opening serial port {SERIAL_PORT}: {e}")
        return

    print("Connected to UART. Starting data capture for 1 minute...")

    # Initialize data storage
    data = {
        'Timestamp': [],
        'Intensity (%)': [],
        'ADC Value': []
    }

    start_time = time.time()
    duration = 60  # Duration in seconds

    while (time.time() - start_time) < duration:
        try:
            if ser.in_waiting:
                line = ser.readline().decode('utf-8').strip()
                if line:
                    # Expected format: "I:<intensity>,ADC:<adc_value>"
                    parts = line.split(',')
                    intensity_part = parts[0].split(':')
                    adc_part = parts[1].split(':')
                    intensity = int(intensity_part[1])
                    adc_value = int(adc_part[1])
                    timestamp = datetime.now().strftime('%H:%M:%S')
                    
                    # Append data
                    data['Timestamp'].append(timestamp)
                    data['Intensity (%)'].append(intensity)
                    data['ADC Value'].append(adc_value)
                    
                    print(f"{timestamp} - Intensity: {intensity}%, ADC: {adc_value}")
        except Exception as e:
            print(f"Error reading line: {e}")
        time.sleep(0.1)  # Prevents high CPU usage

    ser.close()
    print("Data capture complete.")

    # Create DataFrame
    df = pd.DataFrame(data)

    # Generate CSV filename based on current timestamp
    timestamp_str = datetime.now().strftime('%Y%m%d_%H%M%S')
    csv_filename = f"GroupName_Data_{timestamp_str}.csv"  # Replace 'GroupName' with your actual group name

    # Save to CSV
    df.to_csv(csv_filename, index=False)
    print(f"Data saved to {csv_filename}")

    # Plotting
    plt.figure(figsize=(14, 8))

    # Plot Intensity vs Time
    plt.subplot(2, 1, 1)
    plt.plot(df['Timestamp'], df['Intensity (%)'], color='blue', label='Intensity (%)')
    plt.title('LED Intensity Over Time')
    plt.xlabel('Time (HH:MM:SS)')
    plt.ylabel('Intensity (%)')
    plt.xticks(rotation=45)
    plt.legend()
    plt.grid(True)

    # Plot ADC Value vs Time
    plt.subplot(2, 1, 2)
    plt.plot(df['Timestamp'], df['ADC Value'], color='green', label='ADC Value')
    plt.title('ADC Reading Over Time')
    plt.xlabel('Time (HH:MM:SS)')
    plt.ylabel('ADC Value')
    plt.xticks(rotation=45)
    plt.legend()
    plt.grid(True)

    plt.tight_layout()
    plot_filename = f"GroupName_Plot_{timestamp_str}.png"  # Replace 'GroupName' with your actual group name
    plt.savefig(plot_filename)
    plt.show()
    print(f"Plots saved to {plot_filename}")

if __name__ == "__main__":
    main()
```

**Explanation**:

1. **Serial Configuration**:
   - **`SERIAL_PORT`**: Update to match your system's UART port.
   - **`BAUD_RATE`**: Ensure it matches your microcontroller's UART baud rate (e.g., 4800).

2. **Data Reception and Parsing**:
   - Reads incoming UART data line by line.
   - Expects data in the format `I:<intensity>,ADC:<adc_value>`.
   - Parses intensity and ADC values and records them with timestamps.

3. **Data Logging**:
   - Stores data in a dictionary and converts it to a pandas DataFrame.
   - Saves the DataFrame to a CSV file named with the current date and time.

4. **Plotting**:
   - Generates two subplots:
     - **LED Intensity Over Time**: Plots intensity percentage vs. time.
     - **ADC Reading Over Time**: Plots ADC values vs. time.
   - Saves the plots as PNG files.

5. **Error Handling**:
   - Includes try-except blocks to handle potential errors during serial communication and data parsing.

6. **Customization**:
   - Replace `'GroupName'` in filenames with your actual group name as per assignment instructions.

7. **Usage**:
   - Ensure the Python environment has `pyserial`, `pandas`, and `matplotlib` installed.
   - Run the script:
     ```bash
     python uart_data_logger.py
     ```
   - Ensure the microcontroller is transmitting data during the script's execution.

---

## Final Recommendations

1. **Testing**:
   - **Incremental Testing**: Start by testing individual functionalities (e.g., PWM, blinking, UART transmission) before integrating them.
   - **UART Communication**: Use serial terminal software (like RealTerm or PuTTY) to monitor UART data and verify the format before connecting with the Python script.

2. **Debouncing**:
   - Ensure button debouncing is effectively handled to prevent false triggers. Consider using timers or state-based debouncing within ISRs.

3. **Documentation**:
   - **State Diagram**: Create a state diagram illustrating the FSM, showing states and transitions based on button inputs.
   - **Code Comments**: Ensure your code is well-commented for clarity and ease of understanding.

4. **Power Efficiency**:
   - Utilize low-power modes (`Idle()`) effectively.
   - Ensure timers and peripherals are only active when necessary.

5. **Code Optimization**:
   - Avoid blocking calls within ISRs.
   - Ensure that the main loop remains responsive and handles flags appropriately.

6. **Group Collaboration**:
   - Work collaboratively with your group members to divide tasks (e.g., one handles C code, another handles Python scripting).

7. **Final Submission**:
   - Ensure all deliverables (C code, Python script, CSV files, plots, state diagram) are prepared and organized as per assignment requirements.
   - Test the entire system thoroughly to ensure smooth operation during the demo.

Good luck with your project! If you encounter specific issues or have further questions, feel free to ask.

turns-00052.parquet:48546

7f2119a18a552d0830c0ad9e
turn 1/7gpt-4o-2024-08-06EnglishChina449 words
degenerate_repetitionAbsentFinal dense release
USER
import os
from PIL import Image
import cv2
import numpy as np

# 定义路径和阈值
gt_dir = '/home/notebook/data/group/Ruby/stereo-from-mono/dirty_results'
pred_dir = '/home/notebook/data/group/Ruby/stereoProject/test_results'
output_dir = '/home/notebook/data/group/Ruby/depthrefine/mask'
thresholds = [5, 10, 15]  # 示例阈值

# 确保输出目录存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 获取所有真实图像和预测图像的文件名
gt_files = [f for f in os.listdir(gt_dir) if f.endswith('_disp.png')]
pred_files = [f for f in os.listdir(pred_dir) if f.endswith('_pred.png')]

# 创建两个集合来存储去掉后缀的文件名
gt_basenames = {f.replace('_disp.png', '') for f in gt_files}
pred_basenames = {f.replace('_pred.png', '') for f in pred_files}

# 找到两个集合中公共的文件名,即为有效的图像对
common_basenames = gt_basenames.intersection(pred_basenames)

for basename in common_basenames:
    gt_path = os.path.join(gt_dir, f"{basename}_disp.png")
    pred_path = os.path.join(pred_dir, f"{basename}_pred.png")
    print(basename)

    # 打开图像
    gt = cv2.imread(gt_path, cv2.IMREAD_GRAYSCALE)
    pred = cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE)

    # 检查尺寸是否匹配
    if gt.shape != pred.shape:
        print(f"跳过 {basename}:尺寸不匹配。")
        continue

    # 计算绝对差值
    err = cv2.absdiff(gt, pred)

    # 根据不同阈值创建掩码
    for threshold in thresholds:
        # 创建初始为零的掩码
        mask = np.zeros_like(err, dtype=np.uint8)

        # 仅保存像素差值大于阈值的部分
        mask[err > threshold] = 255

        # 保存掩码
        mask_output_path = os.path.join(output_dir, f"{basename}_mask_thr{threshold}.png")
        cv2.imwrite(mask_output_path, mask)
ASSISTANT
This script compares the disparity maps from ground truth images (`_disp.png`) and predicted images (`_pred.png`), finds their absolute differences, and creates binary masks highlighting areas where the predicted disparity values deviate from the ground truth by more than certain thresholds (5, 10, and 15 in this case).

### Key Steps in the Process:

1. **Paths and Preparation**: 
   - Set up directories for input ground truth images (`gt_dir`), predicted images (`pred_dir`), and output masks (`output_dir`).
   - Ensure the output directory exists using `os.makedirs`.

2. **File Matching**:
   - Retrieve lists of ground truth and predicted files.
   - Extract base file names (without suffixes like `_disp.png` or `_pred.png`).
   - Identify common file base names to process corresponding image pairs.

3. **Image Processing**:
   - For each matching pair of images:
     - Load the images in grayscale using OpenCV.
     - Ensure the loaded images have matching dimensions.
     - Compute the absolute pixel-wise difference.

4. **Thresholding**:
   - For each defined threshold, create a binary mask indicating where the absolute difference exceeds the threshold value.
   - Store these masks as binary images, with pixel values set to 255 (white) where the condition holds true.

### Notes:
- **Error Handling**: If the dimensions of ground truth and predicted images don’t match, it skips processing for that image pair.
- **Output**: Creates multiple mask files per image pair (one for each threshold), stored with names reflecting the threshold value.

### Improvements and Considerations:
- **Efficiency**: If images are large, read and process them in chunks or optimize I/O operations.
- **Logging**: Improve logging for better status updates and error handling.
- **Unit Testing**: Add checks for file existence and accessibility to prevent runtime errors.

This script is valuable especially in computer vision tasks that require evaluating accuracy of depth estimation or disparity prediction models by focusing on areas where predictions diverge beyond acceptable levels.

turns-00052.parquet:48547

c3bcc5fd8fc5f6d2a876dac2
turn 2/7gpt-4o-2024-08-06EnglishChina155 words
degenerate_repetitionAbsentFinal dense release
USER
请把这个代码遍历数据改成从小到大的遍历
ASSISTANT
要让代码使用从小到大的顺序来遍历数据,我们需要确保对文件名进行排序。下面是根据文件名排序后的修改版本:

```python
import os
import cv2
import numpy as np

# 定义路径和阈值
gt_dir = '/home/notebook/data/group/Ruby/stereo-from-mono/dirty_results'
pred_dir = '/home/notebook/data/group/Ruby/stereoProject/test_results'
output_dir = '/home/notebook/data/group/Ruby/depthrefine/mask'
thresholds = [5, 10, 15]  # 示例阈值

# 确保输出目录存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 获取所有真实图像和预测图像的文件名
gt_files = sorted([f for f in os.listdir(gt_dir) if f.endswith('_disp.png')])
pred_files = sorted([f for f in os.listdir(pred_dir) if f.endswith('_pred.png')])

# 创建两个集合来存储去掉后缀的文件名
gt_basenames = sorted({f.replace('_disp.png', '') for f in gt_files})
pred_basenames = sorted({f.replace('_pred.png', '') for f in pred_files})

# 找到两个集合中公共的文件名,即为有效的图像对
common_basenames = sorted(gt_basenames.intersection(pred_basenames))

for basename in common_basenames:
    gt_path = os.path.join(gt_dir, f"{basename}_disp.png")
    pred_path = os.path.join(pred_dir, f"{basename}_pred.png")
    print(basename)

    # 打开图像
    gt = cv2.imread(gt_path, cv2.IMREAD_GRAYSCALE)
    pred = cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE)

    # 检查尺寸是否匹配
    if gt.shape != pred.shape:
        print(f"跳过 {basename}:尺寸不匹配。")
        continue

    # 计算绝对差值
    err = cv2.absdiff(gt, pred)

    # 根据不同阈值创建掩码
    for threshold in thresholds:
        # 创建初始为零的掩码
        mask = np.zeros_like(err, dtype=np.uint8)

        # 仅保存像素差值大于阈值的部分
        mask[err > threshold] = 255

        # 保存掩码
        mask_output_path = os.path.join(output_dir, f"{basename}_mask_thr{threshold}.png")
        cv2.imwrite(mask_output_path, mask)
```

### 主要修改点:
- **使用 `sorted()` 函数**:我们对文件名列表和文件基名集合应用了 `sorted()` 函数,以确保遍历是按字母顺序(从小到大)的方式进行的。
- **一致性**:在获取文件名和基名列表时都应用了排序,这样可以确保文件对是正确匹配的。 

如果需要根据特定的规则(如数值顺序而非字母顺序)排序文件名,请确保文件名能正确地反映这种顺序(例如,使用固定长度的数字部分)。

turns-00052.parquet:48548

cc49035c917f6706dd6629cd
turn 3/7gpt-4o-2024-08-06EnglishChina239 words
degenerate_repetitionAbsentFinal dense release
USER
代码报错
ASSISTANT
如果代码出现报错,可能涉及文件路径、文件名排序或图像处理等问题。为了协助排查问题,请确认以下几点:

1. **检查路径和文件名**:
   - 确保 `gt_dir` 和 `pred_dir` 指定的路径存在且包含期望格式的文件(如 `_disp.png` 和 `_pred.png` 后缀的文件)。
   - 确保输出目录 `output_dir` 可写。

2. **文件名排序**:
   - 在通过 `sorted()` 函数对列表排序时,如果文件名包含数字,可能需要按自然排序顺序进行。这可以通过引入 `natsort` 库(需额外安装)来实现。

3. **安装 Image 和 cv2 库**:
   - 确保 Python 环境中已安装 Pillow 和 OpenCV 库。可以通过 `pip` 安装:`pip install pillow opencv-python`.

4. **调试输出**:
   - 添加打印语句来输出文件名和路径,确保程序正在访问正确的文件。
   - 检查 `cv2.imread` 返回结果,确保图像文件正确加载。

以下是一些代码调整来帮助排查错误:

```python
import os
import cv2
import numpy as np
# from natsort import natsorted  # 使用natsorted替换sorted,如果需要自然顺序

# 定义路径和阈值
gt_dir = '/home/notebook/data/group/Ruby/stereo-from-mono/dirty_results'
pred_dir = '/home/notebook/data/group/Ruby/stereoProject/test_results'
output_dir = '/home/notebook/data/group/Ruby/depthrefine/mask'
thresholds = [5, 10, 15]  # 示例阈值

# 确保输出目录存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 获取所有真实图像和预测图像的文件名
gt_files = sorted([f for f in os.listdir(gt_dir) if f.endswith('_disp.png')])
pred_files = sorted([f for f in os.listdir(pred_dir) if f.endswith('_pred.png')])

# 收集基名
gt_basenames = {f.replace('_disp.png', '') for f in gt_files}
pred_basenames = {f.replace('_pred.png', '') for f in pred_files}

# 找到公共基名
common_basenames = sorted(gt_basenames.intersection(pred_basenames))
# 或者使用自然排序:
# common_basenames = natsorted(gt_basenames.intersection(pred_basenames))

for basename in common_basenames:
    gt_path = os.path.join(gt_dir, f"{basename}_disp.png")
    pred_path = os.path.join(pred_dir, f"{basename}_pred.png")
    print(f"Processing: {basename}")  # 调试信息

    # 打开图像
    gt = cv2.imread(gt_path, cv2.IMREAD_GRAYSCALE)
    pred = cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE)

    # 确认图像加载
    if gt is None:
        print(f"Failed to load ground truth image: {gt_path}")
        continue
    if pred is None:
        print(f"Failed to load predicted image: {pred_path}")
        continue

    # 检查尺寸是否匹配
    if gt.shape != pred.shape:
        print(f"Skipping {basename}: Dimension mismatch.")
        continue

    # 计算绝对差值
    err = cv2.absdiff(gt, pred)

    # 根据不同阈值创建掩码
    for threshold in thresholds:
        mask = np.zeros_like(err, dtype=np.uint8)
        mask[err > threshold] = 255

        mask_output_path = os.path.join(output_dir, f"{basename}_mask_thr{threshold}.png")
        cv2.imwrite(mask_output_path, mask)
        print(f"Saved mask: {mask_output_path}")
```

上述代码包含一些调试文本,可以帮助确认程序是否正确地读取了文件和执行了图像处理步骤。请在适当的 IDE 或控制台中运行此代码,并根据错误信息进行调整。

turns-00052.parquet:48549

6c057b0a7cd8be0d82e98499
turn 4/7gpt-4o-2024-08-06EnglishChina217 words
degenerate_repetitionAbsentFinal dense release
USER
Traceback (most recent call last):
  File "mask_gen.py", line 24, in <module>
    common_basenames = sorted(gt_basenames.intersection(pred_basenames))
AttributeError: 'list' object has no attribute 'intersection'
ASSISTANT
报错信息显示 `gt_basenames` 和 `pred_basenames` 是 `list` 类型,但 `intersection` 是 `set` 类型特有的方法。我们需要确保这两个变量在计算交集时是集合类型 (`set`) 而不是列表 (`list`)。以下是修正的代码:

```python
import os
import cv2
import numpy as np

# 定义路径和阈值
gt_dir = '/home/notebook/data/group/Ruby/stereo-from-mono/dirty_results'
pred_dir = '/home/notebook/data/group/Ruby/stereoProject/test_results'
output_dir = '/home/notebook/data/group/Ruby/depthrefine/mask'
thresholds = [5, 10, 15]  # 示例阈值

# 确保输出目录存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 获取所有真实图像和预测图像的文件名
gt_files = sorted([f for f in os.listdir(gt_dir) if f.endswith('_disp.png')])
pred_files = sorted([f for f in os.listdir(pred_dir) if f.endswith('_pred.png')])

# 使用集合来保存基名
gt_basenames = {f.replace('_disp.png', '') for f in gt_files}
pred_basenames = {f.replace('_pred.png', '') for f in pred_files}

# 找到两个集合中公共的文件名(基名)
common_basenames = sorted(gt_basenames.intersection(pred_basenames))

for basename in common_basenames:
    gt_path = os.path.join(gt_dir, f"{basename}_disp.png")
    pred_path = os.path.join(pred_dir, f"{basename}_pred.png")
    print(f"Processing: {basename}")

    # 打开图像
    gt = cv2.imread(gt_path, cv2.IMREAD_GRAYSCALE)
    pred = cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE)

    # 确认图像加载
    if gt is None:
        print(f"Failed to load ground truth image: {gt_path}")
        continue
    if pred is None:
        print(f"Failed to load predicted image: {pred_path}")
        continue

    # 检查尺寸是否匹配
    if gt.shape != pred.shape:
        print(f"Skipping {basename}: Dimension mismatch.")
        continue

    # 计算绝对差值
    err = cv2.absdiff(gt, pred)

    # 根据不同阈值创建掩码
    for threshold in thresholds:
        mask = np.zeros_like(err, dtype=np.uint8)
        mask[err > threshold] = 255

        mask_output_path = os.path.join(output_dir, f"{basename}_mask_thr{threshold}.png")
        cv2.imwrite(mask_output_path, mask)
        print(f"Saved mask: {mask_output_path}")
```

### 主要修正点:
- 确保 `gt_basenames` 和 `pred_basenames` 是使用集合表达式 `{}` 创建的集合,而不是列表。
- 在计算交集时,集合允许使用 `intersection()` 方法,这样可以正确找出两个目录共有的文件基名。

请尝试运行经过修改后的代码。如果错误信息依然出现,请提供更多关于运行环境或错误信息的细节以便进一步排查。

turns-00052.parquet:48550

e1737d9c7e51aa3bc2399a67
turn 5/7gpt-4o-2024-08-06EnglishChina209 words
degenerate_repetitionAbsentFinal dense release
USER
请把上述代码改成从5000开始遍历
ASSISTANT
如果需要从文件名为5000(或拥有5000作为名称一部分)的文件开始遍历,可以在获取公共基名之后进行过滤,确保只处理那些大于等于5000的基名。不过,这取决于文件名的结构(例如,是否为纯数字或包含前缀)。下面是假设基名为纯数字的示例处理:

```python
import os
import cv2
import numpy as np

# 定义路径和阈值
gt_dir = '/home/notebook/data/group/Ruby/stereo-from-mono/dirty_results'
pred_dir = '/home/notebook/data/group/Ruby/stereoProject/test_results'
output_dir = '/home/notebook/data/group/Ruby/depthrefine/mask'
thresholds = [5, 10, 15]  # 示例阈值

# 确保输出目录存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 获取所有真实图像和预测图像的文件名
gt_files = sorted([f for f in os.listdir(gt_dir) if f.endswith('_disp.png')])
pred_files = sorted([f for f in os.listdir(pred_dir) if f.endswith('_pred.png')])

# 使用集合来保存基名
gt_basenames = {f.replace('_disp.png', '') for f in gt_files}
pred_basenames = {f.replace('_pred.png', '') for f in pred_files}

# 找到两个集合中公共的文件名(基名)
common_basenames = sorted(gt_basenames.intersection(pred_basenames))

# 过滤出从5000开始的基名
start_value = 5000
filtered_basenames = [b for b in common_basenames if int(b) >= start_value]

for basename in filtered_basenames:
    gt_path = os.path.join(gt_dir, f"{basename}_disp.png")
    pred_path = os.path.join(pred_dir, f"{basename}_pred.png")
    print(f"Processing: {basename}")

    # 打开图像
    gt = cv2.imread(gt_path, cv2.IMREAD_GRAYSCALE)
    pred = cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE)

    # 确认图像加载
    if gt is None:
        print(f"Failed to load ground truth image: {gt_path}")
        continue
    if pred is None:
        print(f"Failed to load predicted image: {pred_path}")
        continue

    # 检查尺寸是否匹配
    if gt.shape != pred.shape:
        print(f"Skipping {basename}: Dimension mismatch.")
        continue

    # 计算绝对差值
    err = cv2.absdiff(gt, pred)

    # 根据不同阈值创建掩码
    for threshold in thresholds:
        mask = np.zeros_like(err, dtype=np.uint8)
        mask[err > threshold] = 255

        mask_output_path = os.path.join(output_dir, f"{basename}_mask_thr{threshold}.png")
        cv2.imwrite(mask_output_path, mask)
        print(f"Saved mask: {mask_output_path}")
```

### 主要调整:
- 添加 `start_value = 5000`,用于过滤从5000或更高数字开始的基名。
- 使用列表推导式 `[b for b in common_basenames if int(b) >= start_value]` 对 `common_basenames` 进行过滤,确保只包含符合条件的基名。

请确保你的基名是纯数字,这样 `int(b)` 可以正确转换。如果基名包含前缀或者其他字符,你需要根据实际情况调整解析方法。

turns-00052.parquet:48551

5befdd7dba6ceb9b0b04686c
turn 6/7gpt-4o-2024-08-06EnglishChina215 words
degenerate_repetitionAbsentFinal dense release
USER
改成仅仅处理文件名在5000到5450之间的图像
ASSISTANT
为了处理文件名在5000到5450之间的图像,我们需要进一步调整过滤条件,以确保只处理满足该条件的文件名。假设文件名是纯数字形式的基名(去掉后缀后的文件名),代码可以这样写:

```python
import os
import cv2
import numpy as np

# 定义路径和阈值
gt_dir = '/home/notebook/data/group/Ruby/stereo-from-mono/dirty_results'
pred_dir = '/home/notebook/data/group/Ruby/stereoProject/test_results'
output_dir = '/home/notebook/data/group/Ruby/depthrefine/mask'
thresholds = [5, 10, 15]  # 示例阈值

# 确保输出目录存在
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 获取所有真实图像和预测图像的文件名
gt_files = sorted([f for f in os.listdir(gt_dir) if f.endswith('_disp.png')])
pred_files = sorted([f for f in os.listdir(pred_dir) if f.endswith('_pred.png')])

# 使用集合来保存基名
gt_basenames = {f.replace('_disp.png', '') for f in gt_files}
pred_basenames = {f.replace('_pred.png', '') for f in pred_files}

# 找到两个集合中公共的文件名(基名)
common_basenames = sorted(gt_basenames.intersection(pred_basenames))

# 过滤出文件名在5000到5450之间的基名
start_value = 5000
end_value = 5450
filtered_basenames = [b for b in common_basenames if start_value <= int(b) <= end_value]

for basename in filtered_basenames:
    gt_path = os.path.join(gt_dir, f"{basename}_disp.png")
    pred_path = os.path.join(pred_dir, f"{basename}_pred.png")
    print(f"Processing: {basename}")

    # 打开图像
    gt = cv2.imread(gt_path, cv2.IMREAD_GRAYSCALE)
    pred = cv2.imread(pred_path, cv2.IMREAD_GRAYSCALE)

    # 确认图像加载
    if gt is None:
        print(f"Failed to load ground truth image: {gt_path}")
        continue
    if pred is None:
        print(f"Failed to load predicted image: {pred_path}")
        continue

    # 检查尺寸是否匹配
    if gt.shape != pred.shape:
        print(f"Skipping {basename}: Dimension mismatch.")
        continue

    # 计算绝对差值
    err = cv2.absdiff(gt, pred)

    # 根据不同阈值创建掩码
    for threshold in thresholds:
        mask = np.zeros_like(err, dtype=np.uint8)
        mask[err > threshold] = 255

        mask_output_path = os.path.join(output_dir, f"{basename}_mask_thr{threshold}.png")
        cv2.imwrite(mask_output_path, mask)
        print(f"Saved mask: {mask_output_path}")
```

### 主要调整:
- 设置 `start_value` 为 5000 和 `end_value` 为 5450。
- 使用条件 `if start_value <= int(b) <= end_value` 对 `common_basenames` 进行过滤,以确保只处理文件名在指定范围内的图像。

确保文件名是可以转换为整数的格式,如果存在其他谜题或者字符,你需要调整 `int(b)` 的解析逻辑。