Skip to content

Samk humidity control#121

Draft
samkno1 wants to merge 26 commits into
developfrom
samk_humidity_control
Draft

Samk humidity control#121
samkno1 wants to merge 26 commits into
developfrom
samk_humidity_control

Conversation

@samkno1

@samkno1 samkno1 commented Aug 28, 2022

Copy link
Copy Markdown
Collaborator

Humidity controller created.

Assumptions:

  1. Single humidity sensor.

@samkno1 samkno1 requested review from Niuslar and Vavat August 28, 2022 21:25

@Vavat Vavat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sam, this is very good. Nicely done. Let's have pair programming session sometime next week to go through key problems. Specifically, ::run() method. We can then discuss hardware testing. I am in the process of building actual chamber, so this is the right time I think.

Comment thread Controllers/CHumidityController.h Outdated
#include "CPIDLoop.h"
#include "IHardwareMap.h"

#define CHANNEL_NUMBER 8

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have multiple channels?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the temperature controller code, it looks like a heater is assigned per channel. In my humidity controller code, I utilize all the heaters in changing the humidity.

Comment thread Controllers/CHumidityController.h Outdated
private:
void sendStatus(IComChannel *p_comchannel);
ICommand::command_error_code_t setHumidity(ICommand *p_command);
ICommand::command_error_code_t overrideHeater(ICommand *p_command);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you made an assumption that we are going to use heater as a humidifier. For now this is acceptable, but since part of the goal here is to educate you I thought I'd be appropriate to demonstrate how this would be working in a more advanced object oriented design.
Since we right now don't know what humidifier we are going to use, a more flexible design decision would have been to have another class
CHumidifier with methods such as CHumidifier::startEvaporation() and CHumidifier::stopEvaporation() or something along those lines.
Having said that, your design is fairly easy to adapt to having external humidifier and we will perhaps do that once this bit is done.

Comment thread Controllers/CHumidityController.h Outdated

IHardwareMap *mp_hw;

CBME280 *hum_sensor;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This member variable should be called CBME280* mp_humidity_sensor
mp_ prefix means that it's a member pointer. Also, we try to avoid shortening names since it detracts from readability.

Comment thread Controllers/CHumidityController.h Outdated

CBME280 *hum_sensor;

float target_humidity;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_target_humidity

Comment thread Controllers/CHumidityController.cpp Outdated
{
if (actual_humidity != target_humidity)
{
if (actual_humidity < target_humidity)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire if... else... construct is unnecessary. CPIDLoop class will take care of it automatically if you set it up correctly. Let's discuss this part of the code in pair programming session.

Comment thread Controllers/CHumidityController.cpp Outdated
for (int i = 0; i < CHANNEL_NUMBER; i++)
{
float power = 0;
actual_humidity = hum_sensor->getHumidity();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to call humidity sensor withing the loop. The value of actual humidity is not going to change, so you are just wasting cycles. This entire construct is a bit confusing to me, so perhaps we should have a pair programming session to discuss what you were trying to achieve and how to best approach it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can talk about it during the session.

Comment thread Controllers/CHumidityController.cpp Outdated
}
mp_hw->setHardPwmOutput(power, i);
}
while (actual_humidity != target_humidity)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

::run() method must exist. This version of the method hogs the control until humidity is reached. The superloop design pattern assumes that each controller will execute ::run() method to do quick work and exit. Looping like you did will likely cause a lock up since nothing else is getting processed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, didn't think of that

Comment thread Controllers/CHumidityController.cpp Outdated
bool b_command_recognised = false;
ICommand::command_error_code_t result = ICommand::COMMAND_OK;
/**
* Query about current state of all active channels.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the things you will need to learn is where to comment. One habit that is worth developing is avoiding comments. If you feel like a piece of code requires comment, then first thing you should consider is whether you should refactor it to make code very clear and not require comments.
This type of comment is superfluous. Your code is very clean and easy to read, so cluttering it with comments that do not really add new information is detrimental.
Generally, comments should be placed where complex piece of logic is happening, e.g. you're doing some numerical approximation using your own algorithm. Or you have implemented another algorithm in which case brief description is in order and then a reference to a book or a website where algorithm is described in details. Another possibility for comments are in places where you have optimised the if... else construct for execution speed and this reduced readability, but you really want speed improvement, so explain what you've done.
This will come with experience, so don't worry about it too much now, but try to follow the principle.

}

/**
* @brief Set humidity value

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete doxy header. Should have
@param p_command field.
We need to make sure you have right setup to do automatic doxygen headers generation.

@Vavat

Vavat commented Sep 20, 2022

Copy link
Copy Markdown
Collaborator

@samkno1, when you address the issues raised during the code review, you can mark them as resolved.

@samkno1

samkno1 commented Sep 30, 2022

Copy link
Copy Markdown
Collaborator Author

@Vavat I intend on implementing the humidifier class to control the humidifier device. Since this is the case, do I currently need to worry about including the IHardwareMap class in my code since all access to external hardware will go through either the CHumidifier class or the CBME280 class

@Vavat

Vavat commented Oct 1, 2022

Copy link
Copy Markdown
Collaborator

@samkno1, when you think you have addressed all review comments and pushed new code you need to request review again. This restarts review process with your new code. Three are circular arrows next to the reviewers name - mine in this case - that will notify me that new changes are ready for review.

@Vavat Vavat self-requested a review October 1, 2022 12:09
@Vavat

Vavat commented Oct 1, 2022

Copy link
Copy Markdown
Collaborator

@samkno1, when you think you have addressed all review comments and pushed new code you need to request review again. This restarts review process with your new code. Three are circular arrows next to the reviewers name - mine in this case - that will notify me that new changes are ready for review.

@samkno1, I have clicked the request review, but then realised you may not have pushed everything, so let's follow proper process. When you think code is ready, let me know.

@samkno1

samkno1 commented Oct 1, 2022 via email

Copy link
Copy Markdown
Collaborator Author

@Vavat

Vavat commented Oct 2, 2022

Copy link
Copy Markdown
Collaborator

@samkno1, in the meantime I am going to create a humidifier interface within the hardware maps. You can choose to merge them to your code when they are ready.

@samkno1

samkno1 commented Oct 2, 2022

Copy link
Copy Markdown
Collaborator Author

@samkno1, in the meantime I am going to create a humidifier interface within the hardware maps. You can choose to merge them to your code when they are ready.

Sounds good

@samkno1

samkno1 commented Oct 16, 2022

Copy link
Copy Markdown
Collaborator Author

@Vavat You mentioned the runtime for which CDispatcher will run the humidity controller. Is the run time something I need to define somewhere?

@samkno1

samkno1 commented Oct 16, 2022

Copy link
Copy Markdown
Collaborator Author

I have the CPIDLoop defining the power variable for the humidifier

@Vavat You mentioned the runtime for which CDispatcher will run the humidity controller. Is the run time something I need to define somewhere?

Never mind. I just realized I included it as an argument in the Humidity controller class constructor.

@Vavat Vavat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have a pair programming session as soon as you can.

@@ -8,6 +8,7 @@
#include "CHumidityController.h"
#include <stdio.h>
#include "CBME280.h"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header files that are included in CHumidityController.h do not need to be included here. They will be visible. Only include here header file for own class and whatever headers you need to operate, e.g. stdio.h.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted. I was a bit confused about including header files in the .cpp and .h. Thanks

#include "CHumidityController.h"
#include <stdio.h>
#include "CBME280.h"
#include "CHumidifier.h"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used? This might have been something legacy or something I introduced. Check if it does anything and if not remove.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I included that while I was previously using the CHumidifier class to do the humidifier abstraction. I forgot to remove it since it's no longer being used.

Comment thread Controllers/CHumidityController.cpp Outdated

CBME280 hum_temp_reader(p_spi, p_slave_select_port, slave_select_pin);
hum_sensor = &hum_temp_reader;
CBME280 humidity_sensor(p_spi, p_slave_select_port, slave_select_pin);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of these operations? Line 36 already creates humidity_sensor, so reassigning its pointer to another variable is useless operation. Am I missing something?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is related to your comment on the SPI port not being set up. When I directly use the CBME280 humidity_sensor object. I get the following error "error: 'humidity_sensor' was not declared in this scope". So I opted for dynamically accessing the class with the m_humidity sensor pointer to the CBME280 class.

@@ -32,8 +33,8 @@ CHumidityController::CHumidityController(IHardwareMap *p_hardware,
// TODO Auto-generated constructor stub

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realised that this constructor is not going to work because when CHumidityController is created, the SPI port hardware will not be setup yet, so the constructor pointers will be all nullptr. This is actually quite important aspect of c++ for you to understand, so let's have a pair programming session. Drop me an invite.

float actual_humidity;
for (int i = 0; i < CHANNEL_NUMBER; i++)
float power = 0;
if (m_power_override == DISABLE_OVERRIDE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend that special numbers are not used. They can be confusing. I would recommend that you create a special member variable bool mb_humidifier_override;. Move power variable from ::run() method into becoming actual member variable m_power. Then logic becomes much cleaner.

if (!mb_humidifier_override)
{
    ... here you do the control of power since power is not overriden.
}
mp_hw->setHumidifierPower(m_power);

m_power is set to override value when command to override is executed.
This is much cleaner to read and is much less likely to cause confusion with API.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when processing commands, if you get a command that overrides the power, then you simply toggle mb_power_override.

}
float power = *p_command;

// Execute command

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary comment. And it's wrong, since you are sanitising before executing.

Comment thread Controllers/CHumidityController.cpp Outdated
{
return ICommand::ERROR_ARG_COUNT;
}
float power = *p_command;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a mistake. To access first argument of the command it should be:

float power = (*p_command)[0];

{
power = MAX_POWER;
}
if ((power < MIN_POWER) && (power != DISABLE_OVERRIDE))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is complex logic and would be much easier if you used boolean switch to control override.

}
if (b_command_recognised)
{
switch (result)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is now a method in CController that will do what this switch statement does, so you can take advantage of it.


void CHumidityController::sendStatus(IComChannel *p_comchannel)
{
etl::string<MAX_STRING_SIZE> message;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are currently discussing how to return responses to be understood by higher layers. This might change drastically in the future.

@samkno1 samkno1 marked this pull request as draft December 26, 2022 20:01
@Vavat Vavat self-requested a review February 22, 2023 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants